为什么 class.__weakref__ 不是 None,而 instance.__weakref__ 是 None?

4
__weakref__与弱引用相关。我完全理解弱引用的概念以及何时需要使用它们。唯一让我困惑的是以下描述:
一个实例本身没有属性__weakref__,不同于类,因此实例从类中继承__weakref__,这意味着A.__weakref__应该与A().__weakref__相同:
>>> class A: pass
...
>>> A().__dict__            # Each instance starts out as an empty namespace 
{}
>>> A.__weakref__ is None; 
False
>>> A().__weakref__ is None   #But this is True!
True 

为什么`A.__weakref__`不是`None`,而`instance.__weakref__`是`None`,即使实例从类中继承了`__weakref__`?

1
这意味着 A.__weakref__A().__weakref__ 是不同的,因此您假设“实例从类继承 __weakref__”是不正确的。A.__weakref__ is A().__weakref__ 的结果为 False - jonrsharpe
1个回答

5
一个类有一个 __weakref__ 数据描述符属性; 这个属性的作用就像一个 property; 只有在你在实例上访问这个属性时,它才会自动绑定。弱引用的实际数据存储在 C 结构中,是 Python 在内存中表示类和实例所使用的数据结构的一部分。
因此,实例不需要自己的 __weakref__ 属性。类描述符被绑定到实例数据结构上,然后 C 代码只需查找正确的 C struct 来检索所需的信息。
在类上访问该属性会产生描述符对象本身。这不是 None;它是描述符对象。在实例上,绑定的属性会产生弱引用。没有弱引用意味着返回 None
您可以通过访问 A.__dict__['__weakref__'](绕过正常的 type.__getattribute__() 绑定行为),然后直接调用 __get__ 来重新创建描述符行为:
>>> import weakref
>>> class A(object): pass
...
>>> a = A()
>>> A.__weakref__
<attribute '__weakref__' of 'A' objects>
>>> descriptor = A.__dict__['__weakref__']
>>> descriptor.__get__(None, A)
<attribute '__weakref__' of 'A' objects>
>>> a = A()
>>> a.__weakref__ is None
True
>>> descriptor.__get__(a) is None
True
>>> wr = weakref.ref(a)  # add a weak reference
>>> wr
<weakref at 0x10bd86d68; to 'A' at 0x10bad3588>
>>> a.__weakref__
<weakref at 0x10bd86d68; to 'A' at 0x10bad3588>
>>> descriptor.__get__(a)
<weakref at 0x10bd86d68; to 'A' at 0x10bad3588>

我可以问一下你为什么提到了“绕过正常的type.__getattribute__()绑定行为”吗?我可以看到print(A.__weakref__ is A.__dict__["__weakref__"])是True。我的意思是,__weakref__不是一个类属性,恰好是类命名空间中的描述符吗?在其__getattribute__方法中,type元类是否对“__weakref__”键执行了某些操作? - S.B

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接