2011-08-07 9 views
5

可能性の重複:
Why doesn't the weakref work on this bound method?弱参照メソッドは使用できますか?

コンテキストのビット:

私は、リスナー(またはオブザーバー、同じこと)パターンを実装しようとしていた:EventManagerは、リストを保持していますイベントに関心のあるすべてのListenersハンドラのうちの1つです。たとえば、リスナーオブジェクトはonEndOfTheWorldEventメソッドを持ち、イベントクラスEndOfTheWorldEventのインスタンスが転記されるたびにEventManagerによって呼び出されます。簡単です。

リスナーがもう必要なくなったときにEventManagerがハンドラ(バインドされたメソッド)を有効にしないようにするために、ハンドラを弱くしたかったのを除きました。

私は「すべてのハンドラーをWeakSetに投げよう」と考えました。私はそれを働かせることができませんでした。

ここにコードをダンプします(または、最小限に抑えるために残っているものは、ここでは1つのタイプのイベントと1つのタイプのハンドラのみです)。

#! /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を作成できません:

は、それがさらに簡単にするには?そうでない場合、 なぜ

私はWeakSetをWeakKeyDictionaryに置き換えることをお勧めします:キーはリスナー自体であり、ハンドラを評価します。本当に私はリスナーを弱めることができます。しかし、それはデータ構造をもう少し複雑にし、誰にもイベントをブロードキャストする時間が来たら、その構造にはもう一つのレベルがあります。

あなたはどう思いますか?

+0

この質問はバック "メタ" を取得することができ、したがって、この

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

のようにそれにweakrefsを得ることができますそれは解決策に焦点を当てているだけでなく、「なぜ」ではないからです。ここで受け入れられる良い答えを聞かせてください。せいぜい、他の質問には、「これは他の質問への答えを意味する」という意味で重複するものとしてマークすることができます。 – kxr

答えて

8

たとえば、メソッド "meth"にweakrefsが必要だとしましょう。

あなたはその

obj = weak_obj() 
func = weak_func() 

のようにそれをDEREFと

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

うわー、きちんとしたトリック。私はこれらのim_selfとcoを前に見る必要はなかった。 – Niriel

+0

実際には、バインドされたメソッドがインスタンスを参照するため、インスタンスがWeakKeyDictionaryから消えないので、私はそれが必要でした。ありがとう! – Niriel

+3

Python 2.6から、これらのオブジェクトへの優先アクセスがオブジェクトの 'bound_method .__ self__'であり、関数の' bound_method .__ func__'であると思われます。 –

2

listener.handlerは、毎回その関数への新しいバインド参照を提供します。それで、すぐにガベージコレクションが行われます。

+0

実際、「is」との比較は常にFalseを返します。それからもう一度私はそれがちょうど奇妙な大会だったと思った。 – Niriel

関連する問題