为什么Python不会在这个另一个描述符内部调用该函数描述符?
我有如下代码:
class Identity:
def __init__(self, value):
self.value = value
def __get__(self, obj, objtype=None):
return self.value
def __set__(self, obj, value):
self.value = value
class Example:
@Identity
def non_method():
pass
现在,我很惊讶的是,当我调用
>>> example = Example()
>>> example.non_method
<function Example.non_method at 0x72b74d4cb5e0>
得到的是一个函数,而不是一个绑定的方法。
在我看来,return self.value 在 Identity.__get__ 中应该触发存放在 self.value 的原始 non_method 函数的描述符行为,并返回一个绑定到 Identity 对象的方法,因此 return self.value 应该大致执行 return getattr_static(self, "value").__get__(self, type(self))。
起初我以为函数对象可能会检查它是否被绑定到最初定义它的类,但事实并非如此:
>>> import inspect
>>> example.non_method.__get__(inspect.getattr_static(example, "non_method"), Identity)
<bound method Example.non_method of <__main__.Identity object at 0x72b74d5b3230>>
(注意,由于我对这种行为感到神秘,这里的 example.non_method 是未绑定的函数 non_method)
这是怎么回事?为什么函数的描述符不触发?
解决方案
这是因为 self.value 在 Identity 中是在实例对象的 __dict__(若定义了 __slots__,则是在插槽中)进行查找,而不是在类中。
例如,考虑:
class Ten:
def __get__(self, obj, objtype=None):
return 10
class Example:
ten = Ten()
>>> Example.ten
10
>>> example = Example()
>>> example.ten = Ten()
>>> example.ten
<__main__.Ten object at 0x7fcd829ebed0>
来自类和来自对象的查找是透明地交错进行的,这意味着你很难分辨到底发生了哪一种。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。