Calling 'del' on a list
Asked Answered
V

3

5
class ToBeDeleted:
    def __init__(self, value):
        self.value = val

    # Whatever...

    def __del__(self):
        print self.value

l = [ToBeDeleted(i) for i in range(3)]
del l

This prints 2, 1, 0.


  • Now, is the order of the deleted elements defined somewhere in specification or is it implementation-specific? (or maybe I don't understand the underlying mechanics)

  • Could the output, for example, be 0, 1, 2? I realize the 2, 1, 0 order is probably done to avoid the memory reallocations for the elements while deleting them, but still the question remains.

  • And the last one - what's the difference between del l and del l[:] statements?

Volant answered 20/11, 2011 at 22:2 Comment(2)
Very much doubt that the order of calls to __del__() is specified anywhere. Don't even think about trying to write code that relies on a particular ordering.Jeer
Even if the order was specified, you can hold references to list elements anywhere, so the order in which your __del__ methods get called would be different than the order in which the references are removed from the list.Cavern
C
8

Running del l will remove any reference to the list, so the symbol l will be gone. In contrast, running del l[:] removes the contents of the list, leaving l as an empty list.

The __del__ method is what runs when the last reference to an instance is being destroyed.

The order of deletion isn't specified and is implementation specific. When you run del l, the only thing that is guaranteed is that the reference count for the list l and each of its elements will decrease by one.

With pypy, nothing else will happen until the garbage collector is run. The order of the object removal depends on the order that GC visits the objects.

In cpython, the OP was correct in observing that reference decrementing occurs right-to-left. When invoking del l[:] here is the code used to decrement the refcounts: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l700 . When del l is invoked, similar code is used to decrement the refcounts: http://hg.python.org/cpython/file/2.7/Objects/listobject.c#l596

Ceto answered 20/11, 2011 at 22:4 Comment(1)
Thank you. But what about the order of deleted elements?Volant
B
2

Others have already answered. I'll just add what I found in CPython sources.

The list_dealloc function in listobject.c file contains this comment immediately before looping over list items to decrement their reference counts:

    /* Do it backwards, for Christian Tismer.
       There's a simple test case where somehow this reduces
       thrashing when a *very* large list is created and
       immediately deleted. */
Biz answered 20/11, 2011 at 22:21 Comment(1)
Great find! This is also fairly strong evidence that the deletion order is unspecified and might not ever be.Cavern
T
1
  • Deletion order is implementation-specific.
  • Per the answer to the first point, yes it could delete it in some other order (even elements first, random, whatever), and avoiding reallocations has little to do with it. It's just a matter of how the implementation chooses to walk the children. Perhaps the memory allocator is happier if the order of freeing reverses the order of allocating; but that's just a guess.
  • del l deletes the variable itself (and thus the list, if nothing else holds it), whereas del l[:] removes all the elements from the list. Try del l; print l.
Tisiphone answered 20/11, 2011 at 22:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.