什么是__del__方法,如何调用它?

Ver*_*tex 90 python oop

我正在读代码.有一个类__del__定义了哪个方法.我发现这个方法用于销毁类的实例.但是,我找不到使用此方法的地方.主要原因是我不知道如何使用这种方法,可能不是这样:obj1.del().那么,我的问题是如何调用该__del__方法?感谢您的任何帮助.

ily*_* n. 143

__del__终结者.当对象被垃圾收集时调用它,该对象在删除对象的所有引用之后的某个时刻发生.

在一个简单的例子中,这可能是在你说,del x或者,如果x是一个局部变量,在函数结束后.特别是,除非有循环引用,否则CPython(标准Python实现)将立即进行垃圾收集.

但是,这是CPython 的实现细节.Python垃圾收集的唯一必需属性是它所有引用被删除发生,因此这可能不一定发生在之后,可能根本不会发生.

更重要的是,变量可以存在很长时间,原因很多,例如传播异常或模块内省可以使变量引用计数大于0.此外,变量可以是引用循环的一部分- 开启垃圾收集的CPython中断最多但不是全部,这样的周期,甚至只是定期.

由于您无法保证它已被执行,因此应该将您需要运行的代码放入__del__()- 而是,此代码属于块的finally子句trywith语句中的上下文管理器.不过,也有有效的使用情况__del__:例如,如果一个对象X的引用Y,也保留副本Y参考在全球cache(cache['X -> Y'] = Y),那么这将是对礼貌X.__del__也删除缓存条目.

如果你知道析构函数提供了(违反上述指南)必要的清理,你可能想直接调用它,因为它没有什么特别的方法:x.__del__().显然,只有当你知道它不介意被调用两次时你才应该这样做.或者,作为最后的手段,您可以使用重新定义此方法

type(x).__del__ = my_safe_cleanup_method  
Run Code Online (Sandbox Code Playgroud)

  • **CPython实现细节:**CPython目前使用引用计数方案和(可选)循环链接垃圾的延迟检测,...其他实现的行为不同,CPython可能会改变.(http://docs.python.org/2/reference/datamodel.html) (11认同)
  • 你说CPython在引用计数减少到零后立即删除对象的功能是"实现细节".我不相信.你能提供一个备份链接吗?(我的意思是,粗体字**本身相当令人信服,但链接紧随其后...... :-) (4认同)
  • @bombs 它不是析构函数,原因与 __init__ 不是构造函数相同。两者都没有实际创建或销毁该对象。`__init__` 方法初始化一个在调用它时已经存在的对象(这就是为什么它也不返回任何内容)。同样,当 __del__` 退出时,该对象仍然存在:它只是在实际销毁发生之前进行任何可能需要的清理(“终结”)。 (4认同)
  • “可能根本不会发生”包括程序终止的时间吗? (3认同)
  • @AndyHayden:`__del__` 方法即使在程序终止时也可能不会运行,即使它们在终止时运行,编写一个即使在解释器忙于自毁你周围也能正常工作的 `__del__` 方法需要比许多更仔细的编码程序员申请。(CPython 清理通常让 `__del__` 方法在解释器关闭时运行,但仍然存在不够用的情况。守护线程、C 级全局变量以及在另一个 `__del__` 中创建的带有 `__del__` 的对象都可以导致`__del__` 方法未运行。) (2认同)

Cha*_*iam 65

我写了另一个问题的答案,尽管这是一个更准确的问题.

构造函数和析构函数如何工作?

这是一个略微自以为是的答案.

不要用__del__.这不是C++或为析构函数构建的语言.该__del__方法确实应该在Python 3.x中消失,但我确信有人会找到一个有意义的用例.如果您需要使用__del__,请注意每个http://docs.python.org/reference/datamodel.html的基本限制:

但另一方面:

而且我个人不喜欢这个__del__功能的原因.

  • 每当有人提起__del__它时,它就会变成三十条混乱的信息.
  • 它打破了Python的禅宗中的这些项目:
    • 简单比复杂更好.
    • 特殊情况不足以打破规则.
    • 错误不应该默默地传递.
    • 面对模棱两可,拒绝猜测的诱惑.
    • 应该有一个 - 最好只有一个 - 显而易见的方法.
    • 如果实施很难解释,这是一个坏主意.

所以,找个不使用的理由__del__.

  • 即使问题不完全是:为什么我们不应该使用`__del__`,而是如何调用`__del__`,你的答案很有趣. (4认同)
  • 您已经提到“__del__ 在垃圾收集器碰巧收集对象时调用,而不是在您丢失对对象的最后一个引用时调用”。但是,文档明确指出:“注意:del x 不直接调用 x.__del__() — 前者将 x 的引用计数减一,后者仅在 x 的引用计数达到零时调用”。因此,当您丢失对对象的最后一个引用时,始终会调用 __del__。 (3认同)

Jas*_*ker 12

__del__方法将在对象被垃圾收集时调用.请注意,它不一定能保证被调用.以下代码本身不一定会这样做:

del obj
Run Code Online (Sandbox Code Playgroud)

原因是del只将参考计数减1.如果其他东西有对象的引用,__del__则不会被调用.

但是有一些注意事项可以使用__del__.通常,它们通常不是很有用.听起来我更像是想要使用close方法或者使用with语句.

请参阅有关__del__方法python文档.

另外需要注意的是: __del__如果过度使用,方法可以禁止垃圾收集.特别是,具有多个具有__del__方法的对象的循环引用将不会被垃圾收集.这是因为垃圾收集器不知道首先调用哪一个.有关详细信息,请参阅gc模块上的文档.


Nic*_*ood 8

__del__当您的对象最终被销毁时,将调用该方法(注释拼写!).从技术上讲(在cPython中)就是没有更多对你的对象的引用,即当它超出范围时.

如果要删除对象,则调用__del__方法使用

del obj1
Run Code Online (Sandbox Code Playgroud)

这将删除该对象(前提是没有任何其他引用).

我建议你写一个像这样的小班

class T:
    def __del__(self):
        print "deleted"
Run Code Online (Sandbox Code Playgroud)

并在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
>>>   
Run Code Online (Sandbox Code Playgroud)

请注意,jython和ironpython对于删除和__del__调用对象的确切时间有不同的规则.因此,使用它并不被认为是好的做法,__del__并且当它被调用时,对象及其环境可能处于未知状态.它也不是绝对保证__del__- 解释器可以以各种方式退出而不删除所有对象.