2011-08-07 69 views
5

可能重複:
Why doesn't the weakref work on this bound method?我可以弱參考方法嗎?

上下文的位:

我試圖實現一個監聽器(或觀察員,同樣的事情)模式:一種eventmanager進行保存列表所有對事件感興趣的Listener處理程序。例如,一個Listener對象將有一個onEndOfTheWorldEvent方法,每次發佈事件類EndOfTheWorldEvent的一個實例時,該方法將由EventManager調用。簡單。

除了我想弱引用處理程序,因爲我不希望EventManager在不再需要偵聽器時使處理程序(綁定方法)保持活動狀態。

所以我想「讓我們把所有的處理程序放在弱集中」。我無法讓它工作。

我在這裏轉儲代碼(或者當我將它減少到最小值時,這裏只有一種類型的事件和只有一種類型的處理程序)。

#! /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> 

我不能創建在所有weakrefs的方法?如果沒有,爲什麼不是

所以我想一個解決方法是用WeakKeyDictionary替換WeakSet:key是監聽器本身,並且爲處理器賦值。事實上,我可以弱聽我的聽衆。但它使數據結構更加複雜一些,何時可以將這些事件廣播給每個人,這個結構中還有一個層次需要通過。

您認爲如何?

+0

這個問題不是真的重複,因爲它專注於解決方案,而不僅僅是「爲什麼不」。更不用說這裏公認的答案了。在最好的情況下,你可以將另一個問題標記爲重複的:「這個問題意味着對方的答案」。 – kxr

回答

8

假設你想要一個方法「meth」的弱參數。

你可以在它weakrefs這樣

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

所以,你可以DEREF它像

obj = weak_obj() 
func = weak_func() 

並獲得 「甲基」 回來

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

哇,整潔的把戲。我以前從來不需要看這些im_self和co。 – Niriel

+0

實際上,我需要這樣做,因爲綁定的方法引用了實例,因此該實例不會從WeakKeyDictionary中消失。謝謝 ! – Niriel

+3

似乎從Python 2.6向前推進這些對象的首選訪問是對象的'bound_method .__ self__',以及函數的'bound_method .__ func__'。 – 2014-04-20 15:01:15

2

listener.handler每次給你一個新的函數綁定引用。所以它幾乎立即收集垃圾。

+0

事實上,與「is」的比較總是返回False。然後我再次認爲這可能只是一個奇怪的慣例。 – Niriel

相關問題