I was reading a presentation on Pythons' Object model when, in one slide (number
def mul(x, y):
return x * y
mul2 = mul.__get__(2)
mul2(3) # 6
That's Python doing what it does in order to support dynamically adding functions to classes.
__get__ is invoked on a function object (usually done via dot access
. on an instance of a class) Python will transform the function to a method and implicitly pass the instance (usually recognized as
self) as the first argument.
In your case, you explicitly call
__get__ and explicitly pass the 'instance'
2 which is bound as the first argument of the function
>>> mul2 <bound method mul of 2>
This results in a method with one expected argument that yields the multiplication; calling it returns
2 (the bound argument assigned to
x) multiplied with anything else you supply as the argument
Note that normally,
function() invokes it's
__call__ with the appropriate arguments provided:
mul.__call__(2, 3) # 6
As a plus, a Python implementation of
__get__ for functions is provided in the
Descriptor HOWTO document of the Python Docs.
Here you can see the transformation, with the usage of
types.MethodType, that takes place when
__get__ is invoked :
class Function(object): . . . def __get__(self, obj, objtype=None): "Simulate func_descr_get() in Objects/funcobject.c" return types.MethodType(self, obj, objtype)
And the source code for the intrigued visitor is located in
As you can see if this descriptor did not exist you'd have to automatically wrap functions in
types.MethodType any time you'd want to dynamically add a function to class which is an unnecessary hassle.