什么是__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并且在全局cachecache['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__它就变成了三十个混乱的信息。
  • 它打破了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模块上的文档。