WeakValueDictionary saves a link to an object without stronger links

>>> 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 he show this instead of an empty dictionary? Note that this code gives the result I would expect:

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

It also behaves as expected when executing a script (instead of an 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 {} 
+4
source share
3 answers

WeakValueDictionary does not guarantee that entries will be deleted if there are no normal links. It ensures that it does not prevent garbage collection at the right time - your facility will collect garbage, not collect garbage. Recording disappears when garbage collection occurs.

+5
source

If you were only trying to do this in an interactive shell, I suppose this is due to how garbage collection works in this interface and in global operations.

Try this from the 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 the python interactive shell, moving the operation in the scope of functions:

 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
source

In Python Interactive Shell, any variable you declare is not garbage collection automatically, since the scope in __main__ did not end. Python's garbage collection is based on reference counting , and until you do it explicitly or leave the current area, it will not be collected.

In the same shell, if you implement your internal WeakRef function, you will see the expected result, since after the function is completed, the controls go out of scope and objects are garbage collected.

This is why the @jdi example with a function shows you exactly what you want.

+1
source

All Articles