3

I was actually going through descriptors python docs and came across this example

>>> class D(object):
     def f(self, x):
          return x

>>> d = D()
>>> D.__dict__['f'] # Stored internally as a function
<function f at 0x00C45070>
>>> id(D.__dict__['f']) # Memory location
49294384
>>> D.f             # Get from a class becomes an unbound method
<unbound method D.f>
>>> id(D.f )
48549440
>>> d.f             # Get from an instance becomes a bound method
<bound method D.f of <__main__.D object at 0x00B18C90>>
>>> id(d.f)
48549440

So from the above code, I understood that python stores the function definition/declaration of a class as a separate object internally inside class __dict__ variable, when we access directly using __dict__ variable it has memory location as 49294384

But why does it is showing as different function/method object with different memory location 48549440 when accessed through Class or Object? like D.f and d.f

was it not supposed to refer to the same object when we access using the __dict__ variable?. If so why?

3
  • Your code is from Python 2, but the docs you link to are Python 3. "Unbound methods" no longer exist in Python 3. Commented May 15, 2018 at 8:47
  • Related/dupe: Why do different methods have the same id? Commented May 15, 2018 at 8:49
  • @DanielRoseman, yeah sorry for that, I was using Python 2.7, but even the code in documentation is same Commented May 15, 2018 at 8:53

2 Answers 2

2

D.f is a function taking one argument (self)

x = D.f
x(d)

d.f is a "bound method", i.e. a function where the self argument has already been filled in. You can say

x = d.f
x()

Therefor it cannot be the same thing as D.f, and has to be on a different location.

Sign up to request clarification or add additional context in comments.

4 Comments

If you look at my example when I access the function as an attribute the memory location of both ways D.f and d.f was same which I was confused about and what was that behaviour was all about?
Is the id the same thing as 'the memory location'?
Yes exactly, when I refer to memory location it is id
The expression d.f results in a temporary object. Calling it multiple times may result in different results (but memory may be reused). Try [id(x) for x in (d.f, d.f, D.f, D.f)] for instance.
0

xtofi explained the difference between descriptor objects (unbound) and bound methods.

I think the missing part is that bound methods are not kept in memory, and they are actually created every time you access them. (You may get the same memory location, but it's not the same object).

Why? Because on every call on a descriptor may result in a different behavior. Here is an example to explain this idea.

class A(object):
    i = 'a'

    @property
    def name(self):
        if A.i == 'a':
            return self.fa()
        else:
            return self.fb()

    def fa(self):
        print 'one function'

    def fb(self):
        print 'another function'

Calling the function name on an instance of A results in different function calls.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.