Weak Methods September 29, 2006
Many times you would pass bound methods to other functions, as callbacks (i.e., to simulate events,
etc.). However, bound methods (the instancemethod
type) hold a strong reference to their owning
instance (im_self
), which means the existence of a bound method is enough to hold the instance
“alive”, even though your code has lost all references to it.
Sometimes it’s the desired behavior – but not always. This nifty decorator will solve the problem
by returning a “weakly-bound” method, which means the method will not hold the instance alive.
You’ll get ReferenceError
if you try to invoke the method, after the instance has died.
Code
from weakref import proxy
from types import MethodType
class weakmethod(object):
__slots__ = ["func"]
def __init__(self, func):
self.func = func
def __get__(self, obj, cls):
if obj is not None:
obj = proxy(obj)
return MethodType(self.func, obj, cls)
Example
>>> class Foo(object):
... @weakmethod
... def bar(self, a, b):
... print self, a, b
...
>>> f = Foo()
>>> b = f.bar
>>> b
<bound method Foo.bar of <weakproxy at 009FA1E0 to Foo at 009FC070>>
>>> b(1, 2)
<__main__.Foo object at 0x009FC070> 1 2
And when we delete the instance f
:
>>> del f
>>> b
<bound method Foo.bar of <weakproxy at 009FA1E0 to NoneType at 1E1D99B0>>
>>> b(1,2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in bar
ReferenceError: weakly-referenced object no longer exists