2011-08-07 13 views
5

संभव डुप्लिकेट:
Why doesn't the weakref work on this bound method?क्या मैं संदर्भ विधियों को कमजोर कर सकता हूं?

संदर्भ से यह है कि:

मैं एक श्रोता (या ऑब्जर्वर, एक ही बात) को लागू करने की कोशिश कर रहा था पैटर्न: एक EventManager एक सूची रखता है एक कार्यक्रम में दिलचस्पी रखने वाले सभी श्रोताओं के हैंडलर। उदाहरण के लिए, एक श्रोता ऑब्जेक्ट में onEndOfTheWorldEvent विधि होगी जो इवेंट मैनेजर द्वारा प्रत्येक बार इवेंट क्लास EndOfTheWorldEvent पोस्ट करने का उदाहरण पोस्ट किया जाएगा। आसान।

सिवाय इसके कि मैं हैंडलर को कमजोर करना चाहता हूं क्योंकि मैं नहीं चाहता कि इवेंट मैनेजर मेरे हैंडलर (बाध्य विधियों) को जीवित रखने के लिए जीवित रहें जब श्रोता की आवश्यकता नहीं थी।

तो मैंने सोचा "चलो सभी हैंडलर को वीकसेट में फेंक दें"। मैं इसे काम नहीं कर सका।

मैं कोड को यहां डंप करता हूं (या जब मैं इसे कम से कम करता हूं तो इसके बावजूद क्या होता है, यहां केवल एक प्रकार का ईवेंट होता है और केवल एक प्रकार का हैंडलर होता है)।

#! /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 नहीं बना सकता:

तो यह और भी आसान बनाने के लिए? यदि नहीं, क्यों नहीं?

तो मुझे लगता है कि वीकसेट को वीककेई के साथ बदलने के लिए एक कामकाज होगा: कुंजी श्रोता ही है, और हैंडलर का मूल्य है। वास्तव में मैं अपने श्रोताओं को कमजोर कर सकता हूं। लेकिन यह डेटा संरचना को थोड़ा और जटिल बनाता है, और जब घटनाओं को सभी को प्रसारित करने का समय आता है, तो उस संरचना में एक और स्तर होता है।

आपको क्या लगता है?

+0

यह सवाल है के साथ प्राप्त कर सकते हैं वास्तव में डुप्लिकेट नहीं है, क्योंकि यह समाधान पर केंद्रित है और न कि "क्यों नहीं"। यहां अकेले अच्छे स्वीकार्य उत्तर दें। सबसे अच्छा आप दूसरे प्रश्न को इस अर्थ में डुप्लिकेट के रूप में चिह्नित कर सकते हैं: "यह एक दूसरे के जवाब का तात्पर्य है"। – kxr

उत्तर

8

मान लें कि आप "मेथ" विधि पर कमजोर होना चाहते हैं।

आप इस

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

तो जैसे उस पर weakrefs प्राप्त कर सकते हैं, तो आप यह है कि

obj = weak_obj() 
func = weak_func() 

तरह deref और "मेथ" वापस

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

वाह, साफ चाल। मुझे इन im_self और पहले सह देखने के लिए कभी भी जरूरत नहीं थी। – Niriel

+0

असल में, मुझे इसकी आवश्यकता थी, क्योंकि बाध्य विधि उदाहरण का संदर्भ देती है, और इसलिए उदाहरण WeakKeyDictionary से गायब नहीं होता है। धन्यवाद ! – Niriel

+3

लगता है कि पाइथन 2.6 से आगे बढ़ने के लिए पसंदीदा पहुंच आगे बढ़ रही है, वस्तु के लिए 'bound_method .__ self__' है, और फ़ंक्शन के लिए' bound_method .__ func__' है। –

2

listener.handler आपको प्रत्येक बार फ़ंक्शन के लिए एक नया बाध्य संदर्भ देता है। तो यह लगभग तुरंत कचरा इकट्ठा हो जाता है।

+0

दरअसल, "है" के साथ तुलना हमेशा झूठी वापसी करती है। फिर फिर मैंने सोचा कि यह सिर्फ एक अजीब सम्मेलन हो सकता है। – Niriel

संबंधित मुद्दे