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?

Shiva Krishna Bavandla
  • 25,548
  • 75
  • 193
  • 313

2 Answers2

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.

xtofl
  • 40,723
  • 12
  • 105
  • 192
  • 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? – Shiva Krishna Bavandla May 15 '18 at 08:45
  • Is the `id` the same thing as 'the memory location'? – xtofl May 15 '18 at 08:48
  • Yes exactly, when I refer to memory location it is id – Shiva Krishna Bavandla May 15 '18 at 08:49
  • 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. – xtofl May 15 '18 at 09:02
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.

Chen A.
  • 10,140
  • 3
  • 42
  • 61