2011-08-07 3 views
5

가능한 중복 : 문맥의
Why doesn't the weakref work on this bound method?약한 참조 방법을 사용할 수 있습니까?

비트는 :

내가 (또는 관찰자, 같은 일)는 리스너를 구현하기 위해 노력했다 패턴 일 : 개의 EventManager는 목록을 유지 이벤트에 관심이있는 모든 Listeners 핸들러의 목록입니다. 예를 들어 Listener 객체는 EndOfTheWorldEvent 이벤트 클래스의 인스턴스가 게시 될 때마다 EventManager에서 호출하는 onEndOfTheWorldEvent 메서드를가집니다. 쉬운.

Listener가 더 이상 필요하지 않을 때 EventManager가 내 처리기 (바인딩 된 메서드)를 유지하지 않기를 바라기 때문에 핸들러를 약하게 참조하고 싶다는 점을 제외하고는 예외입니다.

그래서 "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> 

나는 전혀 방법에 weakrefs를 만들 수 없습니다 :

는 더 간단하게하려면? 그렇지 않은 경우 을 사용하지 않으시겠습니까?

그래서 WeakSet을 WeakKeyDictionary로 바꾸는 것이 좋습니다. 키는 수신기 자체이며 처리기를 평가합니다. 사실 내 청취자를 약화시킬 수 있습니다. 그러나 데이터 구조가 좀 더 복잡해지며 모든 사람에게 이벤트를 브로드 캐스트 할 시간이 올 경우 해당 구조에서 한 단계 더 나아갑니다.

당신은 어떻게 생각하십니까?

+0

이 질문은 함께 다시 "메타"를 얻을 수 있습니다, 그래서이

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

처럼에 weakrefs를 얻을 수 있습니다 솔루션에 초점을 맞추고 "왜 그렇지 않은가"가 아니라 실제로 중복되지는 않습니다. 혼자 좋은 대답을 여기에합시다. 기껏해야 "다른 하나에 대한 대답"이라는 의미에서 다른 질문을 복제본으로 표시 할 수 있습니다. – kxr

답변

8

"meth"라는 방법에 약점이 있다고 가정 해 봅시다.

당신은 당신이

obj = weak_obj() 
func = weak_func() 

처럼 DEREF 및

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

와우, 깔끔한 속임수. 나는이 im_self와 co를 전에 볼 필요가 없었다. – Niriel

+0

사실, 바인딩 된 메서드가 인스턴스를 참조하므로 인스턴스가 WeakKeyDictionary에서 사라지지 않기 때문에 필자가 필요했습니다. 감사 ! – Niriel

+3

파이썬 2.6에서 우선적으로 이것들에 대한 선호하는 접근이 객체에 대해서는'bound_method .__ self__'이고, 함수에 대해서는'bound_method .__ func__'라고 보입니다. –

2

listener.handler은 매번 함수에 대한 새로운 바운드 참조를 제공합니다. 따라서 거의 즉시 가비지 수집됩니다.

+0

실제로 "is"와의 비교는 항상 False를 반환합니다. 그리고 다시 나는 그것이 단지 이상한 대회 일 수 있다고 생각했다. – Niriel

관련 문제