Python中的weakref到底是什么?
令人惊讶的是,Python中的weakref到底是什么?,python,python-3.x,python-internals,Python,Python 3.x,Python Internals,令人惊讶的是,\uuuuuweakref\uuuuu没有明确的文档。解释了弱引用\uuuuu weakref\uuuuuu的文档中也很快提到了代码>\uuuuuu weakref\uuuuu。但是我找不到任何关于本身的东西 “代码”到底是什么? -它是否只是一个充当标志的成员:如果存在,对象可能被弱引用? -或者它是一个可以被重写/赋值以获得所需行为的函数/变量?如何?变量\uuuu weakref\uuuu是一个属性,它使对象支持弱引用并保留对对象的弱引用 python文档对其进行了如下解释:
\uuuuuweakref\uuuuu
没有明确的文档。解释了弱引用<代码>\uuuuu weakref\uuuuuu的文档中也很快提到了代码>\uuuuuu weakref\uuuuu。但是我找不到任何关于本身的东西
“代码”到底是什么?
-它是否只是一个充当标志的成员:如果存在,对象可能被弱引用?
-或者它是一个可以被重写/赋值以获得所需行为的函数/变量?如何?变量\uuuu weakref\uuuu
是一个属性,它使对象支持弱引用并保留对对象的弱引用
python文档对其进行了如下解释:
当对引用对象的唯一剩余引用是弱引用时,垃圾收集可以随意销毁引用对象并将其内存用于其他用途
因此,弱引用的职责是为对象提供条件,以便能够进行垃圾收集,而不管对象的类型和范围如何
关于\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
,我们可以先查看文档,文档对其进行了
默认情况下,类的实例具有用于属性存储的字典。这会为实例变量很少的对象浪费空间。创建大量实例时,空间消耗可能会变得非常严重
可以通过在类定义中定义\uuuuuu插槽
来覆盖默认值。\uuuuuuuuuuuuuuuuuuuuuuuu
声明获取一系列实例变量,并在每个实例中保留足够的空间来保存每个变量的值。节省空间是因为没有为每个实例创建\uuu dict\uu
现在,由于通过使用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。其中\uuuu weakref\uuuu
是每个对象的必要变量,以便能够处理弱引用
此外,除了所有这些之外,对象的文档说明如下:
可以为该类变量分配一个字符串、iterable或一系列字符串,这些字符串具有实例使用的变量名<代码>\\\\\\\\\/code>为声明的变量保留空间,并防止为每个实例自动创建\\\\\\\\\\\\\\/code>和\\\\\\\\\\/code>
因此,简而言之,我们可以得出结论,\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>用于手动管理存储分配,因为\uuuuuuuuuuuu,因此,\uuuuuuuuuuuuuuuuuuuuuuuuu
将控制\uuuuuuuwakref\uuuuuuuuuuu
属性
此外,文档还向您展示了使用\uuuuuuu插槽\uuuuuu
创建对象以支持弱引用的方法:
>>> import weakref
>>> class A: pass
...
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(a)
>>> c is b, b is a.__weakref__
True, True
>>> weakref.getweakrefs(a)
[<weakref at 0x10dbe5270; to 'A' at 0x10dbc2fd0>]
如果每个实例都没有\uuuuukref\uuuuu
变量,则定义\uuuuuuu插槽的类不支持对其实例的弱引用。如果需要弱引用支持,则将''weakref'
添加到\uuuuu slots
声明中的字符串序列中
以下是python 3.X中的一个示例:
>>> class Test:
... __slots__ = ['a', 'b']
...
>>>
>>> import weakref
>>>
>>> t = Test()
>>>
>>> r = weakref.ref(t)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot create weak reference to 'Test' object
>>>
>>> class Test:
... __slots__ = ['a', 'b', '__weakref__']
...
>>> t = Test()
>>> r = weakref.ref(t)
>>>
>>> t.__weakref__
<weakref at 0x7f735bc55d68; to 'Test' at 0x7f735bc51fc8>
有趣的是,这篇文章在这个话题上没有什么启发性:
如果每个实例都没有\uuuuukref\uuuuu
变量,则定义\uuuuuuu插槽的类不支持对其实例的弱引用。如果需要弱引用支持,则将''weakref'
添加到\uuuuu slots
声明中的字符串序列中
以下选项更有用:
当类型的\uuuu slots\uuuu
声明包含名为\uuuu weakref\uuuu
的插槽时,该插槽将成为该类型实例的弱引用列表头,并且该插槽的偏移量存储在类型的tp\u weaklistoffset
中
弱引用形成堆栈。该堆栈的顶部(对对象的最新弱引用)可通过\uuuuuwakref\uuuu
获得。Weakrefs尽可能重复使用,因此堆栈通常为空或包含单个元素
例子
首次使用weakref.ref()
时,将为目标对象创建一个新的弱引用堆栈。此堆栈的顶部是新的弱引用,并存储在目标对象的\uuuuuuwakref\uuuuu
中:
>>> import weakref
>>> class A: pass
...
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(a)
>>> c is b, b is a.__weakref__
True, True
>>> weakref.getweakrefs(a)
[<weakref at 0x10dbe5270; to 'A' at 0x10dbc2fd0>]
现在c
是堆栈中一个新的弱引用。\uuuuwakref\uuuwk
只是一个不透明对象,将所有弱引用引用引用到当前对象。实际上,它是(或者有时是weakproxy
)的一个实例,它既是对对象的弱引用,也是对该对象所有弱引用的双链接列表的一部分
这只是一个实现细节,允许垃圾收集器通知弱引用其引用对象已被收集,并且不再允许访问其底层指针
弱引用不能依赖于检查它引用的对象的引用计数。这是因为内存可能已被回收,现在正被另一个对象使用。最好的情况是VM崩溃,最坏的情况是弱引用将允许访问它最初没有引用的对象。这就是为什么垃圾收集器必须通知弱引用其引用对象不再有效
有关此对象的结构和C-API,请参见。而实现细节是我在引号文档中没有看到任何关于\uuuuuuweakref\uuuuuuuu
实际功能的内容(它包含弱引用单例)。想补充一下吗?@dhke:这里也一样。。。弱引用的概念很清楚,我真的很想知道的确切含义和功能
>>> import weakref
>>> class A: pass
...
>>> def callback(ref): pass
...
>>> a = A()
>>> b = weakref.ref(a)
>>> c = weakref.ref(a, callback)
>>> c is b, b is a.__weakref__
False, True
>>> weakref.getweakrefs(a)
[<weakref at 0x10dbcfcc0; to 'A' at 0x10dbc2fd0>,
<weakref at 0x10dbe5270; to 'A' at 0x10dbc2fd0>]