什么是__del__方法,如何调用它?
我正在阅读一个代码。 有一个类定义了__del__
方法。 我发现这个方法是用来销毁类的一个实例的。 但是,我找不到使用这种方法的地方。 主要原因是我不知道如何使用这个方法,可能不是这样的: obj1.del()
。 所以,我的问题是如何调用__del__
方法? 感谢您的任何帮助。
__del__
是一个析构函数 。 当一个对象被垃圾回收后,这个对象的所有引用都被删除后被调用。
在简单的情况下,这可能是正确的后,你说del x
或,如果x
是一个局部variables,函数结束后。 特别是,除非有循环引用,否则CPython(标准Python实现)将立即进行垃圾收集。
但是,这是CPython的实现细节 。 Python垃圾收集的唯一必需属性是在所有引用被删除之后发生,所以这可能不是必须发生的, 可能根本不会发生 。
更重要的是,variables可以活很长时间的原因很多 ,例如传播exception或模块自省可以保持variables引用计数大于0.此外,variables可以是引用循环的一部分 – CPython与垃圾收集打开,但不是全部,这样的周期,甚至只是周期性的。
由于你不能保证它被执行,所以不应该把你需要运行的代码放到__del__()
,而是这个代码属于try
块的finally
子句或者在with
语句中的上下文pipe理器。 然而, __del__
有一些有效的用例 :例如,如果一个对象X
引用了Y
并且在全局cache
( cache['X -> Y'] = Y
)中保存了一个Y
引用的副本,那么它将对X.__del__
有礼貌X.__del__
还可以删除caching条目。
如果你知道析构函数提供(违反上述指南)一个必要的清理,你可能想直接调用它 ,因为它没有什么特别的方法: x.__del__()
。 显然,只有当你知道它不介意被调用两次时,你才应该这样做。 或者,作为最后的手段,您可以使用重新定义此方法
type(x).__del__ = my_safe_cleanup_method
我写了另一个问题的答案,虽然这是一个更准确的问题。
有人可以在这里解释python中的构造函数和析构函数 – 需要简单的解释 – 编程新手
这是一个有点自以为是的答案。
不要使用__del__
。 这不是C ++或为析构函数构build的语言。 __del__
方法真的应该在Python 3.x中消失,但我确定有人会find一个有用的用例。 如果您需要使用__del__
,请注意每个http://docs.python.org/reference/datamodel.html的基本限制:;
- 当垃圾收集器恰好在收集对象时调用
__del__
,而不是当您丢失对象的最后一个引用而不是在执行del object
。 -
__del__
负责调用超类中的任何__del__
,尽pipe不清楚这是以方法parsing顺序(MRO)还是只调用每个超类。 - 有一个
__del__
意味着垃圾收集器放弃检测和清理任何循环链接,例如丢失链接列表的最后一个引用。 您可以获取从gc.garbage中忽略的对象列表。 有时你可以使用弱引用来完全避免这个循环。 这个现在得到辩论:请参阅http://mail.python.org/pipermail/python-ideas/2009-October/006194.html 。 -
__del__
函数可以作弊,保存对对象的引用,并停止垃圾收集。 - 在
__del__
中显式引发的exception被忽略。 -
__new__
补充__new__
远远超过__init__
。 这变得混乱。 请参阅http://www.algorithm.co.il/blogs/programming/python-gotchas-1- del -is-the-opposite-of- init /以获得解释和疑难解答。 -
__del__
不是Python中的“受人喜爱”的孩子。 你会注意到sys.exit()文档没有指定是否在退出之前收集垃圾,并且有很多奇怪的问题。 在全局variables上调用__del__
会导致奇怪的sorting问题,例如http://bugs.python.org/issue5099 。 即使__init__
失败,是否应调用__init__
? 请参阅http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423了解较长的线程。;
但另一方面:
-
__del__
意味着你不要忘记打一个__del__
。 请参阅http://eli.thegreenplace.net/2009/06/12/safely-using-destructors-in-python/以获取专业;__del__
观点。 这通常是释放ctypes或其他特殊资源。
而我不喜欢__del__函数的原因。
- 每次有人提起
__del__
它就变成了三十个混乱的信息。 - 它打破了Python中的这些项目:
- 简单胜于复杂。
- 特例不足以打破规则。
- 错误不应该默默通过。
- 面对歧义,拒绝猜测的诱惑。
- 应该有一个 – 最好只有一个 – 明显的方法来做到这一点。
- 如果实施很难解释,这是一个坏主意。
所以,找一个不使用__del__
的理由。
当你的对象被最终销毁时, __del__
方法(注意拼写!)被调用。 从技术上说(在cPython中),就是说当没有更多的引用到你的对象,即当它超出范围。
如果你想删除你的对象,从而调用__del__
方法使用
del obj1
这将删除对象(只要没有任何其他的引用)。
我build议你写一个这样的小class
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 >>>
请注意,jython和ironpython具有不同的规则,以至于何时删除对象并调用__del__。 尽pipe如此,使用__del__
并不被认为是好的做法,事实上,对象及其环境在被调用时可能处于未知状态。 不能绝对保证__del__
被调用 – 解释器可以以各种方式退出而不删除所有对象。
__del__
方法,将在对象被垃圾收集时调用。 请注意,它不一定保证被调用。 下面的代码本身不一定会这样做:
del obj
原因是del
只是将引用计数减1。 如果别的东西有对象的引用, __del__
不会被调用。
尽pipe使用__del__
有一些注意事项。 一般来说,他们通常不是很有用。 这听起来更像是你想使用一个closures的方法或者也许是一个声明 。
请参阅__del__
方法的python文档 。
另外要注意的是: __del__
方法可以在过度使用时抑制垃圾回收。 特别是,具有__del__
方法的多个对象的循环引用不会被垃圾收集。 这是因为垃圾收集器不知道哪一个先打电话。 有关更多信息,请参阅gc模块上的文档。