函数描述符如何工作?

use*_*416 13 python function descriptor python-2.7 python-3.x

当我在一张幻灯片(数字)中断言Pythons的函数是描述符时,我正在阅读关于Pythons的对象模型的演示文稿9.他提出的例子类似于我写的这个例子:

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

mul2 = mul.__get__(2)
mul2(3) # 6
Run Code Online (Sandbox Code Playgroud)

现在,我明白了这一点,因为函数定义了__get__它是一个描述符,正如我在Python文档的描述部分中所描述的那样.

我不明白的是,调用是如何产生输出的.

Jim*_*ard 16

这就是Python为了支持动态地向类添加函数而做的事情.

__get__在函数对象上调用时(通常通过.对类的实例的点访问来完成),Python会将函数转换为方法,隐式地将实例(通常被识别为self)作为第一个参数传递.

在您的情况下,您显式调用__get__显式传递2绑定为函数的第一个参数的"实例" x,这里2被认为是"实例" self:

>>> mul2
<bound method mul of 2> 
Run Code Online (Sandbox Code Playgroud)

这导致在实例2上绑定一个方法,其中一个预期参数产生乘法:调用它返回2(赋值的绑定参数x)乘以您提供的任何其他参数y.

通常,使用提供的适当参数function()调用它__call__:

mul.__call__(2, 3)  # 6
Run Code Online (Sandbox Code Playgroud)

作为一个优点,Python Docs __get__Descriptor HOWTO文档中提供了for函数的Python实现.

在这里,您可以看到调用types.MethodType时发生的转换__get__:

class Function(object):
    . . .
    def __get__(self, obj, objtype=None):
        "Simulate func_descr_get() in Objects/funcobject.c"
        return types.MethodType(self, obj, objtype)
Run Code Online (Sandbox Code Playgroud)

吸引人的访客的源代码位于Objects/funcobject.c.

正如您所看到的,如果此描述符不存在,您必须在types.MethodType您想要动态向类添加函数的任何时候自动换行函数,这是一个不必要的麻烦.