WeakValueDictionary保留对对象的引用,没有更强的引用

时间:2012-08-19 02:19:38

标签: python mapping python-2.7 weak-references

>>> from weakref import WeakValueDictionary
>>> class Foo(object):
...     pass
>>> foo = Foo()
>>> db = WeakValueDictionary()
>>> db['foo-id'] = foo
>>> del foo
>>> dict(db)
{'foo-id': <__main__.Foo object at 0x4dd946c>}

为什么它显示此而不是空字典?请注意,此代码生成我期望的结果:

>>> db2 = WeakValueDictionary()
>>> db2['disposable-id'] = Foo()
>>> dict(db2)
{}

执行脚本(而不是交互式解释器)时,它的行为也符合预期:

from weakref import WeakValueDictionary
class Foo(object):
    pass
foo = Foo()
db = WeakValueDictionary()
db['foo-id'] = foo
del foo
print str(dict(foo))
# prints {}

3 个答案:

答案 0 :(得分:6)

WeakValueDictionary不保证在没有正常引用时将删除条目。它保证的是它不会在适当的时候阻止垃圾收集 - 你的对象是垃圾收集,而不是垃圾收集。垃圾收集发生时,该条目将消失。

答案 1 :(得分:3)

如果你只是在交互式shell中尝试这个,我相信它与垃圾收集在该接口和全局范围操作下的工作方式有关。

从脚本中试试这个:

<强> foo.py

from weakref import WeakValueDictionary

class Foo(object):
    pass

f = Foo()
d = WeakValueDictionary()
d['f'] = f 

print dict(d)
del f 
print dict(d)

然后......

$ python foo.py

{'f': <__main__.Foo object at 0x101f496d0>}
{}

现在,从交互式python shell中尝试这个,在函数范围内移动操作:

from weakref import WeakValueDictionary

class Foo(object):
    pass

f = Foo()
d = WeakValueDictionary()
d['f'] = f 

def main():
    global f
    print dict(d)
    del f 
    print dict(d)

main()

#{'f': <__main__.Foo object at 0x100479f10>}
#{}

答案 2 :(得分:1)

在Python Interactive Shell中,无论您声明什么变量,都不会自动收集垃圾,因为__main__中的范围尚未结束。 Python中的垃圾收集基于引用计数,在您明确执行或取消当前范围之前,它不会被收集。

在同一个shell中,如果在函数内部实现WeakRef逻辑,您将看到预期的结果,因为在完成函数时,控件超出范围并且垃圾收集对象。

这就是为什么@jdi带有功能的例子正在向你展示你想要的东西。