Согласно документации на модуль Weakref:
Далее термин «референт» означает объект, на который ссылаются
по слабой ссылке.
Слабая ссылка на объект не
достаточно, чтобы сохранить объект: когда
единственные оставшиеся ссылки на
Референт слабые ссылки, мусор
коллекция может уничтожить
референт и повторно использовать свою память для
что-то еще.
Что происходит с MyCallbackA, так это то, что вы держите ссылку на него в случаях A, благодаря -
self.MyCallbackA = MyCallbackA
Теперь в вашем коде нет ссылки на связанный метод MyCallbackB. Он содержится только в .__ классе __.__ dict__ как несвязанный метод. По сути, связанный метод создается (и возвращается вам), когда вы делаете self.methodName. (AFAIK, связанный метод работает как свойство, используя дескриптор (только для чтения): по крайней мере, для новых классов стилей. Я уверен, что нечто подобное, то есть без дескрипторов, происходит для классов старых стилей. Я оставлю это кто-то более опытный, чтобы проверить утверждение о классах старого стиля.) Итак, self.MyCallbackB умирает, как только создается слабый ответ, потому что на него нет сильной ссылки!
Мои выводы основаны на: -
import weakref
#Trace is called when the object is deleted! - see weakref docs.
def trace(x):
print "Del MycallbackB"
class A(object):
def __init__(self):
def MyCallbackA():
print 'MyCallbackA'
self.MyCallbackA = MyCallbackA
self._testA = weakref.proxy(self.MyCallbackA)
print "Create MyCallbackB"
# To fix it, do -
# self.MyCallbackB = self.MyCallBackB
# The name on the LHS could be anything, even foo!
self._testB = weakref.proxy(self.MyCallbackB, trace)
print "Done playing with MyCallbackB"
def MyCallbackB(self):
print 'MyCallbackB'
def test_a(self):
self._testA()
def test_b(self):
self._testB()
if __name__ == '__main__':
a = A()
#print a.__class__.__dict__["MyCallbackB"]
a.test_a()
Выход
Создать MyCallbackB
Del MycallbackB
Закончено играть с MyCallbackB
MyCallbackA
Примечание:
Я попытался проверить это для классов старого стиля. Оказалось, что "print a.test_a .__ get__"
выходы -
<method-wrapper '__get__' of instancemethod object at 0xb7d7ffcc>
для новых и старых классов. Так что это может быть не дескриптор, а нечто подобное дескриптору. В любом случае, дело в том, что объект связанного метода создается, когда вы обращаетесь к методу экземпляра через себя, и если вы не будете поддерживать строгую ссылку на него, он будет удален.