WeakrefValueDictionary of Callables?

Steve Holden steve at holdenweb.com
Tue May 23 19:41:35 EDT 2006


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




More information about the Python-list mailing list