我可以弱参考方法吗?

时间:2011-08-07 20:17:41

标签: python weak-references

  

可能重复:
  Why doesn't the weakref work on this bound method?

一点背景:

我试图实现一个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是监听器本身,并为处理程序赋值。的确,我可以削弱我的听众。但是它使得数据结构变得更加复杂,并且当有时间将事件广播给每个人时,该结构中还有一个级别要经过。

您怎么看?

2 个答案:

答案 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每次都为您提供一个新的函数绑定引用。因此几乎立即收集垃圾。