Python:哪些类型支持弱引用?

Cyk*_*ker 11 python weak-references python-internals

码:

from weakref import WeakSet
se = WeakSet()
se.add(1)
Run Code Online (Sandbox Code Playgroud)

输出:

TypeError: cannot create weak reference to 'int' object
Run Code Online (Sandbox Code Playgroud)

Doc:

一些内置类型(如list和dict)不直接支持弱引用,但可以通过子类化添加支持:

...

其他内置类型(如tuple和int)即使在子类化时也不支持弱引用(这是一个实现细节,并且可能在各种Python实现中有所不同).

这表达不足以解释:

  • 为什么有些内置类型不支持弱引用?

  • 那些支持弱引用的类型究竟是什么?


添加一些想法:

对于上面的例子,你可以一个用户定义的包装类内包装的INT,而包装类支持弱引用(那些谁是熟悉Java会记得intInteger):

from weakref import WeakSet
se = WeakSet()

class Integer:
    def __init__(self, n=0):
        self.n = n

i = 1
I = Integer(1)

se.add(i)   # fail
se.add(I)   # ok
Run Code Online (Sandbox Code Playgroud)

我不知道为什么Python不常用的内置类型(提供自动换行int,str等等),而是简单地说,他们不支持弱引用.这可能是由于性能问题,但不能弱化这些内置类型大大减少了它的使用.

use*_*ica 7

第一:这是所有CPython特有的.Weakrefs在不同的Python实现上的工作方式不同.

大多数内置类型不支持弱引用,因为Python的弱引用机制为每个支持弱引用的对象增加了一些开销,Python开发团队决定他们不希望大多数内置类型支付这些开销.这种开销的最简单方式是,任何具有弱引用支持的对象都需要空间来为weakref管理提供额外的指针,并且大多数内置对象不为该指针保留空间.

尝试编译具有弱参考支持的所有类型的完整列表与尝试编译所有红头发人类的完整列表一样富有成效.如果要确定类型是否具有弱引用支持,可以检查它__weakrefoffset__,对于具有弱引用支持的类型,它是非零的:

>>> int.__weakrefoffset__
0
>>> type.__weakrefoffset__
368
>>> tuple.__weakrefoffset__
0
>>> class Foo(object):
...     pass
... 
>>> class Bar(tuple):
...     pass
... 
>>> Foo.__weakrefoffset__
24
>>> Bar.__weakrefoffset__
0
Run Code Online (Sandbox Code Playgroud)

  • 还有一个历史事实是,大多数内置类型早于弱引用,因此添加弱引用支持将导致大量现有 Python 代码的性能回归。但除此之外,我认为这涵盖了一切。 (2认同)