Can I use weak reference methods?

Possible duplicate:
Why does weakref not work on this related method?

A bit of context:

I tried to implement the Listener template (or Observer, the same one): EventManager stores a list of all Listeners handlers interested in the event. For example, the Listener object will have a method onEndOfTheWorldEventthat will be called by the EventManager each time it exposes an instance of the EndOfTheWorldEvent event class. Easy.

Except that I would like to weakly reference handlers, because I do not want the EventManager to keep my handlers (related methods) alive when the Listener is no longer needed.

So I thought, "Drop all handlers in WeakSet." I could not get it to work.

I will give the code here (or what remains of it, when I reduce it to a minimum, there is only one type of event and only one type of handler).

#! /usr/bin/python
"""

"""
import sys
import weakref

class Listener(object):
    def handler(self, event):
        print event

class EventManager(object):
    def __init__(self):
        self.handlers = weakref.WeakSet()
    def register(self, listener):
        print "Registering..."
        self.handlers.add(listener.handler)
        CountRefs(listener.handler)
        print "Number of handlers registered:", len(self.handlers)
        print "Registered."

def CountRefs(what):
    print "Hard count:", sys.getrefcount(what)
    print "Weak count:", weakref.getweakrefcount(what)

listener = Listener()
em = EventManager()
CountRefs(listener.handler)
em.register(listener)
CountRefs(listener.handler)

result:

Hard count: 3
Weak count: 0
Registering...
Hard count: 3
Weak count: 0
Number of handlers registered: 0
Registered.
Hard count: 3
Weak count: 0

It seems like there is never a weak link and the set remains empty.

Make it even easier:

>>> class C(object):
>>>     def blah(self):
>>>         print "blah"
>>> 
>>> c = C()
>>> w = weakref.ref(c.blah)
>>> print w
<weakref at 0x11e59f0; dead>

Can't I create weakrefs for methods in general? If not, why not ?

So, I think a workaround would be to replace WeakSet with WeakKeyDictionary: key is the listener itself and the value of the handler. In fact, I can weaken my listeners. But this makes the data structure a little more complex, and when it comes time to broadcast events for everyone, there is another level in this structure to go through.

What do you think?

+5
source share
2

, , "meth".

weak_obj = weakref.ref(meth.im_self)
weak_func = weakref.ref(meth.im_func)

,

obj = weak_obj()
func = weak_func()

"meth"

meth = getattr(obj, func.__name__)
+8

listener.handler . .

+2

All Articles