WeakValueDictionary retaining reference to object with no more strong references

倖福魔咒の 提交于 2020-01-14 10:09:53

问题


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

Why does it show this instead of an empty dictionary? Note that this code produces the result I'd expect:

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

It also behaves as expected when executing a script (instead of the interactive interpreter):

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

回答1:


WeakValueDictionary does not guarantee that entries will be removed when there are no normal references. What it guarantees is that it will not prevent garbage collection in due course - your object is garbage collectable, not garbage collected. The entry will disappear when garbage collection happens.




回答2:


If you have only been trying this in an interactive shell, I believe it has to do with the way the garbage collection is working under that interface and the global scope operations.

Try this from a script:

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)

And then...

$ python foo.py

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

Now, try this from an interactive python shell, moving the operation under a functions scope:

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



回答3:


In Python Interactive Shell, whatever variable you declare, is not garbage collected automatically, since the scope in __main__ has not ended. Garbage collection in Python is based on reference count, and until you do it explicitly or get off the current scope, it won't be collected.

In same shell, if you implement your WeakRef logic inside function, you will see the expected result, since upon finishing function, controls gets out of scope and objects are collected by garbage.

That's why example by @jdi with function is showing you exactly what you want.



来源:https://stackoverflow.com/questions/12023717/weakvaluedictionary-retaining-reference-to-object-with-no-more-strong-references

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!