Answers:
__del__
是终结器。当删除对象的所有引用之后的某个时刻发生垃圾回收时,调用该方法。
在一个简单的例子中,这可能是在您说完之后,del x
或者如果x
是局部变量,则在函数结束之后。特别是,除非有循环引用,否则CPython(标准Python实现)将立即进行垃圾回收。
但是,这是CPython 的实现细节。Python垃圾回收的唯一必需属性是,它会在删除所有引用之后发生,因此这可能在此之后没有必要发生,也可能根本没有发生。
此外,由于多种原因,变量可以生存很长一段时间,例如,传播异常或模块自省可以使变量引用计数保持大于0。此外,变量可以是引用循环的一部分-启用垃圾回收的CPython多数会中断,但不是全部,这样的周期,甚至只是周期性的。
由于您无法保证它会被执行,因此永远不要将您需要运行的代码放入其中__del__()
-而是,该代码属于块的finally
子句try
或with
语句中的上下文管理器。不过,也有有效的使用情况为__del__
:例如,如果一个对象X
的引用Y
,也保留副本Y
参考在全球cache
(cache['X -> Y'] = Y
),那么这将是一个有礼貌X.__del__
也删除缓存条目。
如果您知道析构函数提供了必要的清除操作(违反了上述准则),则您可能希望直接调用它,因为该方法没有什么特别之处:x.__del__()
。显然,仅当您知道不介意被两次调用时,才应该这样做。或者,作为最后的选择,您可以使用重新定义此方法
type(x).__del__ = my_safe_cleanup_method
__exit__
在这方面?它是在运行之前,之后__del__
还是一起运行?
__del__
方法即使在程序终止时也可能无法运行,即使它们确实在终止时运行,编写一种__del__
即使在解释器忙于自毁时仍能正常工作的方法,需要比许多程序员更仔细地编码。(CPython清理通常使__del__
方法在解释器关闭时运行,但在某些情况下还不够。守护进程线程,C级全局变量以及__del__
在另一个__del__
__del__
我写下了另一个问题的答案,尽管这是一个更准确的问题。
这是一个有点自以为是的答案。
不要使用__del__
。这不是C ++或为析构函数构建的语言。该__del__
方法确实应该在Python 3.x中消失,尽管我确信有人会发现一个有意义的用例。如果您需要使用__del__
,请注意每个http://docs.python.org/reference/datamodel.html的基本限制:
__del__
在垃圾回收器恰好收集对象时调用,而不是在丢失对对象的最后一个引用时而不是在执行时调用del object
。__del__
负责调用__del__
超类中的任何一个,尽管尚不清楚它是按方法解析顺序(MRO)还是仅调用每个超类。__del__
手段,垃圾收集器就放弃检测和清除任何循环链接,例如丢失对链接列表的最后一个引用。您可以获取gc.garbage中忽略的对象的列表。您有时可以使用弱引用来完全避免循环。有时会对此进行辩论:请参阅http://mail.python.org/pipermail/python-ideas/2009-October/006194.html。__del__
函数可以作弊,保存对对象的引用,并停止垃圾回收。__del__
被忽略。__del__
补充__new__
远远不止于__init__
。这变得令人困惑。见http://www.algorithm.co.il/blogs/programming/python-gotchas-1- 德尔 -is-不是最相反OF- 的init /一个解释和陷阱。__del__
在Python中不是一个“受欢迎的”孩子。您会注意到sys.exit()文档没有指定是否在退出之前收集垃圾,并且存在很多奇怪的问题。调用__del__
on全局变量会导致奇怪的排序问题,例如http://bugs.python.org/issue5099。__del__
即使__init__
失败也应该打电话吗?有关长线程的信息,请参见http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423。但另一方面:
__del__
意味着您不会忘记调用结束语。有关专业意见,请参见http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/__del__
。这通常与释放ctype或其他一些特殊资源有关。我不喜欢该__del__
功能的原因。
__del__
它就会演变成三十种混乱的信息。因此,找到不使用的理由__del__
。
__del__
,而是如何调用__del__
,您的回答却很有趣。
该__del__
方法将在垃圾回收对象时被调用。请注意,不一定要调用它。以下代码本身不一定会这样做:
del obj
原因是del
只是将引用计数减一。如果还有其他对象引用,__del__
则不会调用。
__del__
尽管有一些注意事项。通常,它们通常不是很有用。在我看来,这更像是您要使用close方法或with语句。
请参阅有关__del__
方法的python文档。
需要注意的另一件事: __del__
如果使用过多的方法,可能会阻止垃圾回收。特别是,使用一种__del__
方法具有多个对象的循环引用将不会收集垃圾。这是因为垃圾收集器不知道首先调用哪个。有关更多信息,请参见gc模块上的文档。
__del__
当对象最终被销毁时,将调用该方法(请注意拼写!)。从技术上讲(在cPython中),即不再有对您对象的引用,即对象超出范围。
如果要删除对象并因此调用__del__
方法,请使用
del obj1
它将删除该对象(假设没有其他引用)。
我建议你写一个这样的小班
class T:
def __del__(self):
print "deleted"
并在python解释器中进行调查,例如
>>> a = T()
>>> del a
deleted
>>> a = T()
>>> b = a
>>> del b
>>> del a
deleted
>>> def fn():
... a = T()
... print "exiting fn"
...
>>> fn()
exiting fn
deleted
>>>
请注意,关于删除和__del__
调用对象的确切时间,jython和ironpython具有不同的规则。__del__
由于这个原因以及调用对象和其环境可能处于未知状态这一事实,因此不认为使用该方法是一种好习惯。也不绝对保证__del__
会被调用-解释器可以以各种方式退出而不删除所有对象。