user6774416 user6774416 - 27 days ago 7
Python Question

Understanding how function descriptors work for Python

I was reading a presentation on Pythons' Object model when, in one slide (number

9
), the author asserts that Pythons' functions are descriptors. The example he presents to illustrate is similar to this one I wrote:

def mul(x, y):
return x * y

mul2 = mul.__get__(2)
mul2(3) # 6


Now, I understand that the point is made, since the function defines a
__get__
it is a descriptor as I described in the description section of the Python documentation.

What I don't understand is how exactly the call results in the output provided.

Answer

That's Python doing what it does in order to support dynamically adding functions to classes.

When __get__ is invoked on a function object, which is 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 x:

>>> 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 y.


In addition, 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 Objects/funcobject.c.

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, unnecessary hassle.

Comments