问题:什么是__del__方法,如何调用?
我正在阅读代码。有一个__del__定义方法的类。我发现此方法用于销毁该类的实例。但是,我找不到使用此方法的地方。这样做的主要原因是我不知道如何使用此方法,可能不是这样:obj1.del()。那么,我的问题是如何调用该__del__方法?
回答 0
__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  回答 1
我写下了另一个问题的答案,尽管这是一个更准确的问题。
这是一个有点自以为是的答案。
不要使用__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__它就会演变成三十种混乱的信息。
- 它在Python的Zen中打破了这些项目:
- 简单胜于复杂。
- 特殊情况不足以违反规则。
- 错误绝不能默默传递。
- 面对模棱两可的想法,拒绝猜测的诱惑。
- 应该有一种(最好只有一种)明显的方式来做到这一点。
- 如果实现难以解释,那是个坏主意。
 
因此,找到不使用的理由__del__。
回答 2
该__del__方法将在垃圾回收对象时被调用。请注意,不一定要调用它。以下代码本身不一定会这样做:
del obj原因是del只是将引用计数减一。如果还有其他对象引用,__del__则不会调用。
__del__尽管有一些注意事项。通常,它们通常不是很有用。在我看来,这更像是您要使用close方法或with语句。
请参阅有关__del__方法的python文档。
需要注意的另一件事:   __del__如果使用过多的方法,可能会阻止垃圾回收。特别是,使用一种__del__方法具有多个对象的循环引用将不会收集垃圾。这是因为垃圾收集器不知道首先调用哪个。有关更多信息,请参见gc模块上的文档。
回答 3
__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__会被调用-解释器可以以各种方式退出而不删除所有对象。
回答 4
如前所述,该__del__功能有些不可靠。在看起来有用的情况下,请考虑使用__enter__and __exit__方法。这将产生类似于with open() as f: pass用于访问文件的语法的行为。__enter__进入时with,__exit__会自动调用,退出时会自动调用。有关更多详细信息,请参见此问题。

