Lloyd Weehuizen wrote [top-posting, for which he should have his wrist smacked]: > Steve Holden wrote: > > 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? > > > > > > 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 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) > > Thanks for that, I had a feeling that was the problem. Is there anyway > around this? I'd prefer not to have to assume the method name on the object. > > This could be solved by passing the object and method name in as two > separate parameters to the Bind function. But ideally I'd like to > extract this information somehow from the bound method and give the > external API a more natural feel. Is that possible? >
Well, you *could* try extracting the object and the method name from the bound method inside your method. No promises, but let's see ... OK, here's something that allows you to keep the same API. It has the disadvantage of using a dict that parallels the WeakValueDictionary but doesn't drop entries as the wekrefs disappear. Which reminds me, you need to rewrite the code so that the absence of a weakref is correctly detected, which it isn't here. import weakref TEST_EVENT = 1 class TestBinder: def __init__( self ): self.objects = weakref.WeakValueDictionary() self.names = {} def BindFunction( self, event_id, function ): self.objects[event_id] = function.im_self self.names[event_id] = function.im_func.func_name def CallFunction( self, event_id, *args ): getattr(self.objects[event_id], self.names[event_id])( *args ) class TestCase: def __init__( self, binder ): binder.BindFunction( TEST_EVENT, self.TestFunction ) def TestFunction(self): print "TestFunction OK" test_binder = TestBinder() test_case = TestCase( test_binder ) test_binder.CallFunction( TEST_EVENT ) But it gives you a place to start from. Now back to the need for speed. 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 -- http://mail.python.org/mailman/listinfo/python-list