【问题标题】:A non-function __get__ attribute of a descriptor receives an additional argument when called, why?描述符的非函数 __get__ 属性在调用时会收到一个附加参数,为什么?
【发布时间】:2016-11-02 22:54:45
【问题描述】:

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

在下面的示例中,BC 都是非数据描述符(它们具有 __get__ 属性)。 B__get__ 属性是A 的一个实例——它是可调用的——而C 是一个函数的实例(一个函数)——也是可调用的。类DE 有一个名为attr 的属性,其类型分别为BC

根据我对python的属性查找过程的理解,访问D/E的实例的attr属性最终会在D/E.__dict__中找到attr,注册为非数据描述符会返回调用@的结果描述符对象上的 987654338@ - 但是此调用的签名似乎因描述符 __get__ 属性的类型而异。

我没有这个场景的特定用例,但想象A 充当一种有状态的函数类,我可以从设计的角度看到这种行为作为@ 的一种方式是如何有意义的987654341@ 与描述符通信。但是我无法理解为什么会发生这种行为 - 这种行为是隐含的还是我遗漏了什么?

class A(object):
    def __call__(self, desc, obj, cls):
        print 'A::__call__\n'

class B(object):
    __get__ = A()

class C(object):
    def __get__(self, obj, cls):
        print 'C::__get__\n'

class D(object):
    attr = B()

class E(object):
    attr = C()

>>> D().attr
A::__call__
>>> E().attr
C::__get__

【问题讨论】:

    标签: python


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-14
      • 2019-06-13
      • 1970-01-01
      相关资源
      最近更新 更多