7
>>> 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 {}
4

3 回答 3

10

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

于 2012-08-19T05:47:49.200 回答
4

如果您只是在交互式 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>}
#{}
于 2012-08-19T03:10:50.900 回答
3

在 Python 交互式 Shell 中,无论您声明什么变量,都不会自动进行垃圾收集,因为 in 的作用域__main__还没有结束。Python 中的垃圾收集是基于引用计数的,除非你明确地这样做或离开当前范围,否则它不会被收集。

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

这就是为什么@jdi with function 的示例向您展示了您想要的内容。

于 2015-05-13T17:06:04.503 回答