Python weakref运行结果与文档不符:对象删除后弱引用仍处于活跃状态
问题原因
你遇到的现象是交互式运行环境(IPython、Python原生REPL、Jupyter Notebook等)的隐式强引用导致的,和weakref本身的实现逻辑无关。
交互式环境会自动将所有历史输出结果存入全局的Out字典中,你测试代码里Out[5]、Out[6]、Out[8]都存储了该A类实例的强引用,因此你执行del a之后,该实例的引用计数并没有降到0,GC自然不会回收该对象,弱引用自然可以正常获取到实例。
解决方法
方法1:直接用脚本运行测试
将测试代码保存为独立的.py文件直接执行,脚本运行环境不会存储不必要的输出引用,运行以下代码可以得到符合文档描述的结果:
import weakref, gc class A: pass a = A() b = weakref.ref(a) # 此时b()可以拿到实例 print(b()) # 删除唯一的强引用 del a # 引用计数归零后实例直接被回收,无需手动GC print(b())
运行输出如下:
<__main__.A object at 0x7f9b1c0b5120> None
方法2:在交互式环境中清除隐式引用
如果需要在交互式环境中测试,删除对应Out字典中的历史引用后再执行GC即可:
# 删除存储了A实例的所有Out条目 del Out[5], Out[6], Out[8] gc.collect() # 此时b()会返回None print(b())
你提到的另一搁置多年的同类问题也是相同原因,都是没有注意到交互式环境的隐式强引用导致的,按上述方法测试即可得到符合官方文档的结果。
内容的提问来源于stack exchange,提问作者deponovo
相关产品推荐
相关产品推荐

