From the python docs:
It is not guaranteed that
__del__()
methods are called for objects that still exist when the interpreter exits.
Why not? What problems would occur if this guarantee were made?
No, most destructors are not run on exit() . Essentially, when exit is called static objects are destroyed, atexit handlers are executed, open C streams are flushed and closed, and files created by tmpfile are removed.
In C++, we can manage resources by objects, i.e. acquiring resource in Ctor, and releasing it in Dtor (RAII). This relies on C++'s automatic destructor invocation.
When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.
Right Answer is: B 2. False: It is executed whenever an object of its class goes out of scope or whenever the delete expression is applied to a pointer to the object of that class. It is called just before the object go out of scope or just before its life ends. 3.
I'm not convinced by the previous answers here.
Firstly note that the example given does not prevent __del__
methods being called during exit. In fact, the current CPythons will call the __del__
method given, twice in the case of Python 2.7 and once in the case of Python 3.4. So this can't be the "killer example" which shows why the guarantee is not made.
I think the statement in the docs is not motivated by a design principle that calling the destructors would be bad. Not least because it seems that in CPython 3.4 and up they are always called as you would expect and this caveat seems to be moot.
Instead I think the statement simply reflects the fact that the CPython implementation has sometimes not called all destructors on exit (presumably for ease of implementation reasons).
The situation seems to be that CPython 3.4 and 3.5 do always call all destructors on interpreter exit.
CPython 2.7 by contrast does not always do this. Certainly __del__
methods are usually not called on objects which have cyclic references, because those objects cannot be deleted if they have a __del__
method. The garbage collector won't collect them. While the objects do disappear when the interpreter exits (of course) they are not finalized and so their __del__
methods are never called. This is no longer true in Python 3.4 after the implementation of PEP 442.
However, it seems that Python 2.7 also does not finalize objects that have cyclic references, even if they have no destructors, if they only become unreachable during the interpreter exit.
Presumably this behaviour is sufficiently particular and difficult to explain that it is best expressed simply by a generic disclaimer - as the docs do.
Here's an example:
class Foo(object):
def __init__(self):
print("Foo init running")
def __del__(self):
print("Destructor Foo")
class Bar(object):
def __init__(self):
print("Bar1 init running")
self.bar = self
self.foo = Foo()
b = Bar()
# del b
With the del b
commented out, the destructor in Foo
is not called in Python 2.7 though it is in Python 3.4.
With the del b
added, then the destructor is called (at interpreter exit) in both cases.
If you did some nasty things, you could find yourself with an undeletable object which python would try to delete forever:
class Phoenix(object):
def __del__(self):
print "Deleting an Oops"
global a
a = self
a = Phoenix()
Relying on __del__
isn't great in any event as python doesn't guarantee when an object will be deleted (especially objects with cyclic references). That said, perhaps turning your class into a context manager is a better solution ... Then you can guarantee that cleanup code is called even in the case of an exception, etc...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With