[Python-3000] weakrefs of bound methods
Guido van Rossum
guido at python.org
Fri Feb 15 18:35:42 CET 2008
On Fri, Feb 15, 2008 at 2:12 AM, Nick Craig-Wood <nick at craig-wood.com> wrote:
> I've just been bitten yet again by the fact you can't have a weakref
> to a bound method! I find myself wanting to do this whenever I have a
> registry of callback functions.
>
> Could we in py3k either
>
> 1) make weakrefs to bound methods work? A weakref to a bound method
> should mean hold the weakref on the instance and bind the method at
> the last moment.
I think you're somehow confused about how weakrefs are supposed to
work. They work fine!
Python 3.0a2+ (py3k:60836, Feb 15 2008, 09:21:45)
[GCC 4.0.3 (Ubuntu 4.0.3-1ubuntu5)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import weakref
>>> class C:
... def __init__(self, x=0): self.x = x
... def f(self): return self.x
...
>>> f = C(42).f
>>> r = weakref.ref(f)
>>> r
<weakref at 0xf7be8fcc; to 'method' at 0xf7f0c48c (f)>
>>> r()
<bound method C.f of <__main__.C object at 0xf7bfc4ac>>
>>> r()()
42
>>> del f
>>> r()
>>> r
<weakref at 0xf7be8fcc; dead>
>>>
> or
>
> 2) throw an exception when you attempt to take a weak reference of a
> bound method? Maybe only when it has a single refcount?
>
> Eg
>
> Python 3.0a2+ (py3k:60831, Feb 15 2008, 09:52:40)
> [GCC 4.2.3 20071123 (prerelease) (Debian 4.2.2-4)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> from weakref import WeakKeyDictionary
> >>> d=WeakKeyDictionary()
> >>> class A(object):
> ... def f(self): print("hello")
> ...
> >>> a=A()
> >>> a.f()
> hello
> >>> d[a.f] = True
> >>> d.keys()
> []
> >>>
>
> I know how to work around the problem. The fact that it passes
> completely silently uses up lots of developer time debugging it
> though!
Sorry, you don't seem to understand how weak references work.The bound
method object a.f goes away because you're not keeping any other
reference to it. Try this instead:
>>> d = weakref.WeakKeyDictionary()
>>> f = C(100).f
>>> d[f] = 200
>>> d
<WeakKeyDictionary at 4156538988>
>>> d.keys()
[<bound method C.f of <__main__.C object at 0xf7bfc54c>>]
>>> del f
>>> d.keys()
[<bound method C.f of <__main__.C object at 0xf7bfc54c>>]
>>>
>>> 1
1
>>> d.keys()
[]
>>>
(The second time I printed d.keys() it wasn't gone yet because the
hidden variable '_' was holding on to the last object printed, which
was the list of d's keys.)
--
--Guido van Rossum (home page: http://www.python.org/~guido/)
More information about the Python-3000
mailing list