[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