Understanding the behavior of function descriptors
<p>I was reading <a href="http://www.aleax.it/Python/nylug05_om.pdf" rel="nofollow">a presentation</a> on Python's Object model when, in one slide (number <code>9</code>), the author asserts that Pythons' functions are descriptors. The example he presents to illustrate is similar to this one I wrote:</p>

<pre><code>def mul(x, y):
    return x * y

mul2 = mul.__get__(2)
mul2(3) # 6
</code></pre>

<p>Now, I understand that the point is made, since the function defines a <code>__get__</code> it is a descriptor. </p>

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

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

<p>When <code>__get__</code> 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 <code>self</code>) as the first argument. </p>

<p>In your case, you explicitly call <code>__get__</code> and explicitly pass the 'instance' <code>2</code> which is bound as the first argument of the function <code>x</code>:</p>

<pre><code>&gt;&gt;&gt; mul2
&lt;bound method mul of 2&gt; 
</code></pre>

<p>This results in a method with one expected argument that yields the multiplication; calling it returns <code>2</code> (the bound argument assigned to <code>x</code>) multiplied with anything else you supply as the argument <code>y</code>.</p>

<hr>

<p>In addition, a Python implementation of <code>__get__</code> for functions is provided in the <a href="https://docs.python.org/3/howto/descriptor.html#functions-and-methods" rel="nofollow"><code>Descriptor HOWTO</code></a> document of the Python Docs. Here you can see the transformation, with the usage of <a href="https://docs.python.org/3/library/types.html#types.MethodType" rel="nofollow"><code>types.MethodType</code></a>, that takes place when <code>__get__</code> is invoked :</p>

<pre><code>class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj, objtype)
</code></pre>

<p>And the source code for the intrigued visitor is located in <code>Objects/funcobject.c</code>.</p>

<p>As you can see if this descriptor did not exist you'd have to automatically wrap functions in <code>types.MethodType</code> any time you'd want to dynamically add a function to class, unnecessary hassle.</p>

python python-2.7 function python-3.x