>>> 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 {}
__weakref__ is just an opaque object that references all the weak references to the current object. In actual fact it's an instance of weakref (or sometimes weakproxy ) which is both a weak reference to the object and part of a doubly linked list to all weak references for that object.
To create weak references in python, we need to use the weakref module. The weakref is not sufficient to keep the object alive. A basic use of the weak reference is to implement cache or mappings for a large object. Not all objects can be weakly referenced.
A weakly referenced object is cleared by the Garbage Collector when it's weakly reachable. Weak reachability means that an object has neither strong nor soft references pointing to it. The object can be reached only by traversing a weak reference.
A weak reference permits the garbage collector to collect the object while still allowing the application to access the object. A weak reference is valid only during the indeterminate amount of time until the object is collected when no strong references exist.
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.
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>}
#{}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With