[Python-Dev] weakref gc semantics

Tim Peters tim.peters at gmail.com
Thu Nov 4 21:11:32 CET 2004


[James Y Knight]
> An unreachable callback function can also have visible effects.

Quite true -- it might even reformat your hard drives <wink>.

> ...
> From what I'm hearing here, the following two pieces of code would then
> have different behavior under patch-callback:
>
> """
> def C_gone(ignored):
>     print "An object of type C went away."
>
> class C:
>     def __init__(self):
>         self.wr = weakref.ref(self, C_gone)
> """
>
> and
>
> """
> class C:
>     def __init__(self):
>         def C_gone(ignored):
>             print "An object of type C went away."
>         self.wr = weakref.ref(self, C_gone)
> """
>
> If that's correct, it sounds like a bad idea to me.

Assuming you're assuming the same driver is getting used after these
snippets, yes, under patch-callback an instance of C in cyclic trash
in the first case would trigger the callback, but not in the second
case.

I don't know why you believe that's bad:  perhaps you could articulate
a precise set of rules for what would be "good"?  Maybe that's even
the set of rules Python 2.4b2 actually uses.  They seem more or less
arbitrary to me (and so do patch-callback's -- and so do
patch-finalizer's).  For example, you can fiddle your examples above
to get the same kind of "hmm, in one case it does, in the other case
it doesn't" outcome in 2.4b2 by manipulating whether the weakref is
externally reachable, instead of manipulating the reachability of the
callback.  Is that change in *what* you fiddle essentially different,
so that it's "not bad" to get different outcomes when weakref
reachability is fiddled?

I don't think it's obvious, but under patch-finalizer they both get
the same outcome (the callback is invoked, and the weakref gets
deallocated before gc.garbage gets built).  OTOH, if you make C_gone a
method of C, and use self.C_gone as the callback, then the outcome is
different:  then the callback doesn't get called, and c is actually
resurrected under patch-finalizer, even in the driver's first

    print "creating non-cyclic C instance"
    c = C()

case (although the print stmt is no longer truthful then).


More information about the Python-Dev mailing list