Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WeakValueDictionary retaining reference to object with no more strong 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>}

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 {}
like image 970
Jordan Avatar asked Aug 19 '12 02:08

Jordan


People also ask

What is __ Weakref __ in Python?

__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.

How do you use weak references in Python?

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.

How does a weak reference work?

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.

What is weak reference in C#?

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.


2 Answers

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.

like image 50
Marcin Avatar answered Nov 07 '22 22:11

Marcin


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>}
#{}
like image 44
jdi Avatar answered Nov 08 '22 00:11

jdi