__del__ is a finalizer. This is not a destructor. Finalizers and destructors are completely different animals.
Destructors are called reliably and exist only in languages ββwith deterministic memory management (for example, C ++). Python context managers (the with statement) can achieve similar effects under certain circumstances. They are reliable because the service life of an object is precisely fixed; in C ++, objects die when they explicitly delete d or when an area comes out (or when a smart pointer deletes them in response to their own destruction). And this is when the destructors are started.
Finalizers are not called reliably. The only permissible use of the finalizer is the emergency security system (NB: this article is written from a .NET perspective, but the concepts translate intelligently Well). For example, file objects returned by open() are automatically closed upon completion. But you should still close them yourself (for example, using the with statement). This is due to the fact that objects are destroyed dynamically by the garbage collector, which may or may not start immediately, and with the generation garbage collection, it may or may not collect some objects in any given passage. Since no one knows what kind of optimization we can think of in the future, it is safe to assume that you simply cannot know when the garbage collector will collect your objects. This means that you cannot rely on finalizers.
In the specific case of CPython, you get somewhat stronger guarantees through the use of reference counting (which is much simpler and more predictable than garbage collection). If you can guarantee that you will never create a reference loop associated with this object, this object finalizer will be called at a predictable point (when the last link dies). This is true only for CPython, the reference implementation, and not for PyPy, IronPython, Jython, or any other implementation.
Kevin source share