描述符的非函数__get__属性在调用时会收到另一个参数,为什么?

时间:2016-06-30 17:42:26

标签: python

有人可以解释为什么描述符的非函数__get__属性在调用时似乎会收到一个额外的参数 - 即描述符对象(在函数的情况下隐式传递为self)?

在下面的示例中,BC都是非数据描述符(它们具有__get__属性)。 B的{​​{1}}属性是__get__的实例 - 可以调用 - 而A是函数的实例(函数) - 也可以调用。类CD具有名为E的属性,其类型分别为attrB

根据我对python属性查找过程的理解,访问C实例的attr属性最终会在D/E中找到attr并注册它是非数据descriptor将返回在描述符对象上调用D/E.__dict__的结果 - 但是此调用的签名似乎不同,具体取决于描述符__get__属性的类型。

我没有针对这种情况的特定用例,但想象__get__充当一种有状态的函数类我可以从设计的角度看待这种行为是否有意义使A能够与描述符进行通信。但我不能理解为什么这种行为发生 - 这种行为是隐含的还是我错过了什么?

A

1 个答案:

答案 0 :(得分:1)

这与__get__无关。如果不涉及描述符,您将看到相同的效果:

>>> class A(object):
...     def __call__(self, arg):
...         return arg
...
>>> a = A()
>>> def b(arg):
...     return arg
...
>>> a(3)
3
>>> b(3)
3

问题是A.__call__是一个未绑定的方法,而一个函数的签名,特定于该函数类型的特定实例,更类似于绑定方法的签名。

您应该将A.__call__实例的签名与函数的签名进行比较,而不是将A的签名与单个函数的签名进行比较。如上所示,实例的签名和函数完全匹配。或者,您可以将A.__call__types.FunctionType.__call__进行比较,它将函数实例作为其第一个参数:

>>> import types
>>> types.FunctionType.__call__(b, 3)
3