Can someone explain this weakref behavior?
Peter Otten
__peter__ at web.de
Fri Jun 11 13:53:28 EDT 2004
Michael Kent wrote:
> The Python 2.3.4 docs about weakref say:
> Not all objects can be weakly referenced; those objects which can
> include class instances, functions written in Python (but not in C),
> and methods (both bound and unbound).
>
> I've been unable to get using a bound method as the key in a
> WeakKeyDictionary to work. Using a class instance object works fine
> as a key, using a method of that same instance object does not.
> Here's some code, in a file named test_weakref.py:
>
> #! /usr/bin/env python
>
> import unittest
> import weakref
>
> class someClass(object):
> def aMethod(self):
> print "Hi!"
>
> class TestCase_01_weakref(unittest.TestCase):
>
> def test_01_simple(self):
>
> obj1 = someClass()
> obj2 = someClass()
> wkd = weakref.WeakKeyDictionary()
>
> wkd[obj1] = 1
> self.assertEqual(len(wkd), 1)
>
> wkd[obj1.aMethod] = 1
> self.assertEqual(len(wkd), 2)
>
> wkd[obj2.aMethod] = 1
> self.assertEqual(len(wkd), 3)
>
>
> if __name__ == "__main__":
> unittest.main()
>
> And here's the output:
>
> ./test_weakref.py
> F
> ======================================================================
> FAIL: test_01_simple (__main__.TestCase_01_weakref)
> ----------------------------------------------------------------------
> Traceback (most recent call last):
> File "./test_weakref.py", line 22, in test_01_simple
> self.assertEqual(len(wkd), 2)
> File "/usr/local/lib/python2.3/unittest.py", line 302, in
> failUnlessEqual
> raise self.failureException, \
> AssertionError: 1 != 2
>
> ----------------------------------------------------------------------
> Ran 1 test in 0.001s
>
> FAILED (failures=1)
>
> It is acting as though a bound method is silently not allowed as the
> key in a WeakKeyDictionary. Can someone set me straight?
You need a (strong) reference to the bound methods in order to keep them
from being garbage-collected (and therefore removed from the
WeakKeyDictionary) - not keeping alive the referenced keys is pretty much
the WeakKeyDictionary's raison d'être. A modified
def test_01_simple(self):
obj1 = someClass()
obj2 = someClass()
wkd = weakref.WeakKeyDictionary()
m1 = obj1.aMethod
m2 = obj2.aMethod
wkd[obj1] = 1
self.assertEqual(len(wkd), 1)
wkd[m1] = 1
self.assertEqual(len(wkd), 2)
wkd[m2] = 1
self.assertEqual(len(wkd), 3)
should complete without failure.
Peter
More information about the Python-list
mailing list