Garbage collection

Duncan Booth duncan.booth at invalid.invalid
Tue Feb 19 14:25:46 CET 2008

Nick Craig-Wood <nick at> wrote:

> [<__main__.Y object at 0xb7d9fc8c>, <__main__.Y object at 0xb7d9fcac>,
> <__main__.Y object at 0xb7d9fc2c>] [<__main__.Y object at 0xb7d9fc8c>]
> (It behaves slightly differently in the interactive interpreter for
> reasons I don't understand - so save it to a file and try it!)

Any expression in the interactive interpreter is implicitly assigned to 
the variable '_', so after your first call to Y.list() you've saved 
references to the complete list in _. Assignments aren't expressions so 
after assigning to a and c you haven't changed _. If you throw in 
another unrelated expression you'll be fine:

>>> a = Y()
>>> b = Y()
>>> c = Y()
>>> Y.list()
[<__main__.Y object at 0x0117F230>, <__main__.Y object at 0x0117F2B0>, 
<__main__.Y object at 0x0117F210>, <__main__.Y object at 0x0117F670>, 
<__main__.Y object at 0x0117F690>, <__main__.Y object at 0x0117F6B0>, 
<__main__.Y object at 0x0117F310>]
>>> a = 1
>>> c = 1
>>> c
>>> Y.list()
[<__main__.Y object at 0x0117F6B0>]

> In fact I find most of the times I wanted __del__ can be fixed by
> using a weakref.WeakValueDictionary or weakref.WeakKeyDictionary for a
> much better result.

The WeakValueDictionary is especially good when you want a Python 
wrapper round some external non-python thing, just use the address of 
the external thing as the key for the dictionary and you can avoid 
having duplicate Python objects.

The other option for classes involved in a cycle is to move the __del__ 
(and anything it needs) down to another class which isn't part of the 
cycle, so the original example becomes:

>>> class Monitor(object):
	def __del__(self): print "gone"

>>> class X(object):
	def __init__(self):
		self._mon = Monitor()

>>> a = X()
>>> a = 1
>>> b = X()
>>> b.someslot = b
>>> b = 1
>>> import gc
>>> gc.collect()

More information about the Python-list mailing list