从C++转行Python的人可能会认为__del__等价于C++中的Destructor,但同时会发现一些很奇怪的问题,比如在__del__中使用类变量时遇到
Exception AttributeError: "'NoneType' object has no attribute '***'"
的问题。
通过查阅资料,发现__del__不是一般意义上的Destructor,不推荐使用__del__(或者,对于一般人来说,不能使用__del__)。
理由如下:
(1)Circular references which are garbage are detected when the option cycle detector is enabled (it’s on by default), but can only be cleaned up if there are no Python- level __del__() methods involved.Your solution of never building any cycles between objects is difficult to ensure – and mistakenly adding non-weakref’ed cycles adds hard to track memory leaks.(在循环引用的Object链中,__del__不会被GC调用,而你很难保证不会在Object中形成引用链)
下面是从Python的Document中摘取的资料:
A list of objects which the collector found to be unreachable but could not be freed (uncollectable objects). By default, this list contains only objects with __del__() methods.Objects that have __del__() methods and are part of a reference cycle cause the entire reference cycle to be uncollectable, including objects not necessarily in the cycle but reachable only from it.Python doesn’t collect such cycles automatically because, in general, it isn’t possible for Python to guess a safe order in which to run the __del__() methods. If you know a safe order, you can force the issue by examining the garbage list, and explicitly breaking cycles due to your objects within the list. Note that these objects are kept alive even so by virtue of being in the garbage list, so they should be removed from garbage too. For example, after breaking cycles, do del gc.garbage[:] to empty the list. It’s generally better to avoid the issue by not creating cycles containing objects with __del__() methods, and garbage can be examined in that case to verify that no such cycles are being created.
(2)__del__ can be called during program exit – thus the state of your program is completely undefined (for example, modules may have been collected & cleaned out).(__del__被调用时系统的状态可能是不稳定的,因此调用时可能会发生一些无法预测的情况)
下面是从Python的Document中摘取的资料:
Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done),other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.
好多人在回答有关__del__的提问时,都会说“So why does it exist? Beats me.”
来看一下__del__的定义,就会发现有多让人百思不得其解了:
object.__del__(self)
Called when the instance is about to be destroyed. This is also called a destructor. If a base class has a __del__() method, the derived class’s__del__() method, if any, must explicitly call it to ensure proper deletion of the base class part of the instance. Note that it is possible (though not recommended!) for the __del__() method to postpone destruction of the instance by creating a new reference to it. It may then be called at a later time when this new reference is deleted.It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.
看这两句奇葩的话,一方面说它可以被称为是一个Destructor,另一方面又说不保证在Interpreter退出前调用那些还未被回收的Object的__del__方法,那这种Destructor谁还敢用?