This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: weakref cannot handle bound methods (in contrast to docu)
Type: Stage:
Components: Extension Modules Versions:
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: arigo, graik
Priority: normal Keywords:

Created on 2005-05-22 14:37 by graik, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (2)
msg25395 - (view) Author: Raik Gruenberg (graik) Date: 2005-05-22 14:37
According to the documentation of the weakref module,
weakreferences can be applied to
"...class instances, functions written in Python (but
not in C), methods (both bound and unbound)..."

In reality, bound methods cannot be referenced (see bug
813299):

import weakref

## this works:
def testF( event ):    pass
r = weakref.ref( testF )

## this doesnt:
class EventListener:
    def handleEventA( self, event ):
        pass

t = EventListener()
## gives a "dead" ref
r = weakref.ref( t.handleEventA )

This behaviour is unexpected for anyone not aquainted
to the inner clockwork of python and unfortunate
because it, for example, prevents to keep weak
references to callback methods in event handling
patterns.  

A workaround is proposed at
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81253

Discussion:
(minimal) Solution 1:
Change the weakref documentation

(preferred) Solution 2:
Adapt weakref to allow references to bound methods

Perhaps this bug should be converted into a
documentation bug and a feature request.

Python version 2.3 and 2.4
OS: Linux 2.6
msg25396 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2005-05-23 14:08
Logged In: YES 
user_id=4771

Of course, the weakref documentation is ultimately right,
and the problem, unrelated to bound methods, is that you
always get a dead weakref if you do

    weakref.ref(<expr-than-returns-a-new-object>)

But I'm not being particularly helpful here.

A trick simpler than the cookbook proposals is to force the
method object to be alive as long as the instance itself by
storing it on the instance:

    obj = MyClass()
    obj.m = obj.m
    ref = weakref.ref(obj.m)

This works because the last "obj.m" returns an existing
object, as opposed to one created just-in-time.  This
might be mentioned in the weakref documentation with the
comment that it's a general rule to be careful not to take
weakrefs to short-lived object; the same problem would
occur e.g. when taking a weakref to "obj.a" where "a" is
a computed property.  Storing the result back on "obj" --
under the same or another name -- is a workaround.
History
Date User Action Args
2022-04-11 14:56:11adminsetgithub: 42003
2005-05-22 14:37:09graikcreate