Continuing our Python experiments:
Example 1.2. A function is more
>>> class C(object): ... classattr = "attr on class" ... def f(self): ... return "function f" ... >>> C.__dict__{'classattr': 'attr on class', '__module__': '__main__', '__doc__': None, 'f': <function f at 0x008F6B70>} >>> cobj = C() >>> cobj.classattr is C.__dict__['classattr']
True >>> cobj.f is C.__dict__['f']
False >>> cobj.f
<bound method C.f of <__main__.C instance at 0x008F9850>> >>> C.__dict__['f'].__get__(cobj, C)
<bound method C.f of <__main__.C instance at 0x008F9850>>
Two innocent looking class attributes, a string 'classattr' and a function 'f'. | |
Accessing the string really gets it from the class's | |
Not so for the function! Why? | |
Hmm, it does look like a different object. (A bound method is a
callable object that calls a function ( | |
Here's the spoiler - this is what Python did to create the bound
method. While looking for an attribute for an instance, if Python
finds an object with a |
It is only the presence of the __get__() method
that transforms an ordinary function into a bound
method. There is nothing really special about a function
object. Anyone can put objects with a __get__()
method inside the class __dict__ and get away with
it. Such objects are called descriptors and have
many uses.
{'classattr': 'attr on class', '__module__': '__main__',
'__doc__': None, 'f': <function f at 0x008F6B70>}
>>> cobj = C()
>>> cobj.classattr is C.__dict__['classattr']
True
>>> cobj.f is C.__dict__['f']
False
>>> cobj.f
<bound method C.f of <__main__.C instance at 0x008F9850>>
>>> C.__dict__['f'].__get__(cobj, C)
<bound method C.f of <__main__.C instance at 0x008F9850>>