One Python 2.1 idea

Thomas Wouters thomas at xs4all.net
Wed Dec 27 04:41:40 EST 2000


On Wed, Dec 27, 2000 at 03:30:36AM -0500, Tim Peters wrote:
> [Tim]
> > Note:
> >
> > >>> class Oops:
> >         def foo(self):
> >             pass
> >
> > >>> x = Oops()
> > >>> x.foo = x.foo
> > >>> x.foo.im_self is x
> > 1
> > >>>
> >
> > Oops!  That is, x is now involved in a reference cycle (x's
> > dict contains a bound method that points back to x).  Before 2.0,
> > that's a memory leak.  In 2.0, it's a leak only if the class
> > (unlike Oops above) has a __del__ method (or you've disabled
> > cyclic gc).

Funny, I didn't see that original message. I guess the list is still a
little flabergasted over being moved and Barry apparently abandoning it
(because of his lack of connectivity) ;) That's an excellent point, by the
way, '[Tim]' (if indeed that's your name). I hadn't even realized storing
bound methods creates cycles -- another good reason to avoid method-caches ?
:)

Note that a reference cycle isn't a leak in itself, it's merely a very good
recipe for a leak :) In the above cycle, if you never stop referencing 'x',
you don't have a memory leak -- no new 'x.foo' methods are created, and you
aren't growing. And if you do care about both this speed enhancement and are
using it often enough to worry about memory use, try this:

>>> class Oops:
...     def foo(self):
...             pass
... 
>>> x = Oops()
>>> from sys import getrefcount as rc
>>> rc(x)
2
>>> x.foo = x.foo
>>> rc(x)
3
>>> del x.foo
>>> rc(x)
2

Or, to avoid the cycle altogether, don't do 'x.foo = x.foo', do 'foo =
x.foo' instead, and just call 'foo'. 'foo' will still reference 'x', but 'x'
will not reference 'foo'. This trick is often used in the std python lib,
even, so there's enough precedent :-)

-- 
Thomas Wouters <thomas at xs4all.net>

Hi! I'm a .signature virus! copy me into your .signature file to help me spread!




More information about the Python-list mailing list