问题 函数描述符如何工作?


我正在读书 一个演讲 在Pythons的对象模型中,在一张幻灯片中(数字 9),作者断言Pythons的功能是描述符。他提出的例子类似于我写的这个例子:

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

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

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

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


7871
2017-08-30 13:22


起源



答案:


这就是Python为了支持动态地向类添加函数而做的工作。

什么时候 __get__ 在函数对象上调用(通常通过点访问来完成) . 在类的实例上)Python将函数转换为 方法 和 隐式 传递实例(通常被认为是 self)作为第一个论点。

在你的情况下,你 明确地 呼叫 __get__ 和 明确地 通过'实例' 2 它被绑定为函数的第一个参数 x, 这里 2 被认为是“实例” self

>>> mul2
<bound method mul of 2> 

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

一般, function() 调用它 __call__ 提供适当的论据:

mul.__call__(2, 3)  # 6

作为一个加号,Python的实现 __get__ 功能提供在 描述符HOWTO 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)

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

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


13
2017-08-30 13:24