1

Can anyone describe me why this code will print '2 1 0 done' instead of expected output '0 1 2 done'? As i can understand, we have some anonymous variables creating during list comprehensions, and they are garbage-collected, using filo principle, on list comprehension uncoverage end. But, they still are referenced in list aa, aren't they? Why the second 'del a' is not calling del magic method in that case?

class A:
    def __init__(self, name):
        self.name = name
    def __del__(self):
        print self.name,

aa = [A(str(i)) for i in range(3)]
for a in aa:
    del a

print 'done'

Also, advanced questions. Please look at http://codepad.org/niaUzGEy Why there are 5 copies, 3 copies? Musn't this be 1 copy? Why 5 or 3? Dont know, thats why asking it ;) Thanks for your time!

Wooble
  • 87,717
  • 12
  • 108
  • 131

2 Answers2

7

You are confusing the del statement and the __del__ method.

del a simply unbinds the name a from whatever object it referenced. The list referenced by aa is unchanged so the objects all continue to exist.

The __del__ method is only called after the last reference to an object has been destroyed. That could be after a call to __del__ but usually isn't.

You rarely need to use del. It would be much more common just to rebind aa and then all the objects it contains will be released, and if not otherwise referenced their __del__ methods will be called automatically.

Also, you rarely need to use __del__. For most purposes Python's management of objects will handle cleanup automatically. Adding a __del__ method to a class is generally a bad idea as it can interfere with the garbage collector, so rather paradoxically __del__ makes it more likely that your program will leak memory. Also Python won't guarantee whether __del__ is actually called on program exit, and if it does you may find global variables you cant to use no longer exist, nor will it guarantee to only call it once (though you have to jump through hoops to make it call it more than once).

In short, avoid using __del__ if you possibly can.

Duncan
  • 92,073
  • 11
  • 122
  • 156
3

It prints done 2 1 0(CPython).

You don't delete list elements in a for loop. They are deleted on exit. As far as I know call order of __del__ is implementation-specific, so it can be different in another implementations(IronPython, Jython etc.)

cval
  • 6,609
  • 2
  • 17
  • 14