WeakrefValueDictionary of Callables?

Steve Holden steve at holdenweb.com
Sun May 21 08:02:33 CEST 2006


Lloyd Weehuizen wrote:
> Hey
> 
> I'm trying to set up a WeakrefValueDictionary of callables however as 
> soon as my method that adds the callable to the dictionary exits the 
> value is removed? Is there any way around this?
> 
> Example:
> import weakref
> TEST_EVENT = 1
> 
> class TestBinder:
> 	def __init__( self ):
> 		self.entries = weakref.WeakValueDictionary()
> 		
> 	def BindFunction( self, event_id, function ):
> 		self.entries[event_id] = function
> 
> 	def CallFunction( self, event_id, *args ):
> 		self.entries[event_id]( *args )
> 
> 
> class TestCase:
> 	def __init__( self, binder ):
> 		binder.BindFunction( TEST_EVENT, self.TestFunction )
> 		
> 	def TestFunction():
> 		print "TestFunction OK"
> 
> test_binder = TestBinder()
> test_case = TestCase( test_binder )
> 
> test_binder.CallFunction( TEST_EVENT )
> 
> This generates a KeyError: 1, if I don't use weakrefs, then the TestCase 
> object is never cleaned up until TestBinder is destroyed.
> 
I believe your problem is that the bound method references aren't being 
retained (i.e. referenced) anywhere else. A bound method is an object in 
its own right, and can cease to exist at any time - particularly in your 
case when the weak reference is the only reference to it!

Consider that the following code actually appears to work:

import weakref
TEST_EVENT = 1

class TestBinder:
         def __init__(self):
                 self.entries = weakref.WeakValueDictionary()

         def BindFunction(self, event_id, obj):
                 self.entries[event_id] = obj

         def CallFunction(self, event_id, *args):
                 self.entries[event_id].TestFunction(*args)


class TestCase:
         def __init__(self, binder):
                 binder.BindFunction(TEST_EVENT, self)

         def TestFunction(self):
                 print "TestFunction OK"

test_binder = TestBinder()
test_case = TestCase(test_binder)

test_binder.CallFunction(TEST_EVENT)

The difference is that now a reference to the object rather than its 
bound method is stored, and your program *does* contain other references 
to the TesTcase object. It's perfectly leagal to store weak references 
to bound methods, but as you have seen they aren't referenced by their 
parent object.

Further notes: I have cleaned your code up to be closer to PEP 8 
conformance (if you don't know what PEP 8 is you shoudl find out), and I 
added the necessary "self" argument to the TestCase.TestFunction() method.

Hope this helps.

regards
  Steve
-- 
Steve Holden       +44 150 684 7255  +1 800 494 3119
Holden Web LLC/Ltd          http://www.holdenweb.com
Love me, love my blog  http://holdenweb.blogspot.com
Recent Ramblings     http://del.icio.us/steve.holden




More information about the Python-list mailing list