一点背景:
我试图实现一个Listener(或Observer,同样的东西)模式:EventManager保存一个对Event感兴趣的所有Listener处理程序的列表。例如,Listener对象将具有onEndOfTheWorldEvent
方法,每当发布事件类EndOfTheWorldEvent的实例时,EventManager将调用该方法。容易。
除了我想弱引用处理程序,因为我不希望EventManager在不再需要Listener时让我的处理程序(绑定方法)保持活动状态。
所以我想“让我们把所有处理程序都放在WeakSet中”。我无法让它发挥作用。
我在这里转储代码(或者当我将其减少到最小值时剩下的东西,这里只有一种类型的事件,只有一种类型的处理程序。)
#! /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)
结果:
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
它看起来好像从来没有任何弱引用,并且该集合仍然是空的。
使其更简单:
>>> class C(object):
>>> def blah(self):
>>> print "blah"
>>>
>>> c = C()
>>> w = weakref.ref(c.blah)
>>> print w
<weakref at 0x11e59f0; dead>
我不能创建方法的弱参数吗?如果没有,为什么不?
所以我想一个解决方法是用WeakKeyDictionary替换WeakSet:key是监听器本身,并为处理程序赋值。的确,我可以削弱我的听众。但是它使得数据结构变得更加复杂,并且当有时间将事件广播给每个人时,该结构中还有一个级别要经过。
您怎么看?
答案 0 :(得分:8)
假设你想要一个方法“meth”上的weakrefs。
你可以像这样获得弱点
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__)
答案 1 :(得分:2)
listener.handler
每次都为您提供一个新的函数绑定引用。因此几乎立即收集垃圾。