I am curious about the details of __del__ in python, when and why it should be used and what it shouldn’t be used for. I’ve learned the hard way that it is not really like what one would naively expected from a destructor, in that it is not the opposite of __new__ / __init__.
class Foo(object):
def __init__(self):
self.bar = None
def open(self):
if self.bar != 'open':
print 'opening the bar'
self.bar = 'open'
def close(self):
if self.bar != 'closed':
print 'closing the bar'
self.bar = 'close'
def __del__(self):
self.close()
if __name__ == '__main__':
foo = Foo()
foo.open()
del foo
import gc
gc.collect()
I saw in the documentation that it is not guaranteed __del__() methods are called for objects that still exist when the interpreter exits.
- how can it be guaranteed that for any
Fooinstances existing when the interpreter exits, the bar is closed? - in the code snippet above does the bar get closed on
del fooor ongc.collect()… or neither? if you want finer control of those details (e.g. the bar should be closed when the object is unreferenced) what is the usual way to implement that? - when
__del__is called is it guaranteed that__init__has already been called? what about if the__init__raised?
The way to close resources are context managers, aka the
withstatement:output:
2) Python’s objects get deleted when their reference count is 0. In your example the
del fooremoves the last reference so__del__is called instantly. The GC has no part in this.output:
The
gchas nothing to do with deleting your and most other objects. It’s there to clean up when simple reference counting does not work, because of self-references or circular references:output:
3) Lets see:
gives:
Objects are created with
__new__then passed to__init__asself. After a exception in__init__, the object will typically not have a name (ie thef =part isn’t run) so their ref count is 0. This means that the object is deleted normally and__del__is called.