函数描述符是如何工作的?

How do function descriptors work?

我在阅读 a presentation 关于 Python 的对象模型时,在一张幻灯片(第 9 号)中,作者断言 Python 的功能是描述符。他提供的例子与我写的这个相似:

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

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

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

我不明白的是所提供的输出中的调用结果究竟如何。

这就是 Python 所做的,以支持向 classes 动态添加功能。

当在函数对象上调用 __get__ 时(通常通过点访问 . 在 class 的实例上完成)Python 会将函数转换为methodimplicitly 将实例(通常识别为 self)作为第一个参数传递。

在你的例子中,你显式调用__get__并且显式传递'instance'2 绑定为函数 x 的第一个参数,这里 2 被认为是 "instance" self:

>>> mul2
<bound method mul of 2> 

这导致方法绑定在实例 2 上,有一个产生乘法的预期参数:调用它 returns 2(分配给 x 的绑定参数)相乘与您提供的任何其他内容作为参数 y.

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

mul.__call__(2, 3)  # 6

另外,Python 文档的 Descriptor HOWTO 文档中提供了 __get__ 函数的 Python 实现。

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

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

感兴趣的访客的源代码位于 Objects/funcobject.c

如您所见,如果此描述符不存在,您必须在任何时候自动将函数包装在 types.MethodType 中,以便将函数动态添加到 class,这是不必要的麻烦。