【问题标题】:Is __del__ really a destructor?__del__ 真的是析构函数吗?
【发布时间】:2016-10-17 13:54:24
【问题描述】:

我主要在 C++ 中做事,其中析构函数实际上是为了销毁获取的资源。最近我开始使用python(这真的很有趣而且很棒),我开始学习它有像java一样的GC。 因此,没有过多强调对象所有权(构造和销毁)。

据我所知,__init__() 方法在 python 中对我来说比在 ruby​​ 中更有意义,但是__del__() 方法,我们真的需要在我们的班级?如果我错过__del__(),我的班级会缺少什么吗?我可以看到__del__() 有用的一个场景是,如果我想在销毁对象时记录一些东西。除了这个还有别的吗?

【问题讨论】:

  • 没有。你几乎不应该实现__del__
  • 几乎从不想要实现__del__。提供自定义 __del__ 的类在处理循环时必须由 GC 以特殊方式处理(因为 __del__ 必须只调用一次)并且在某些情况下 GC 将无法收集它们 [虽然从 python3.4+ 这已经改进了很多]。在极少数情况下实施它是个好主意。
  • 如果你是 python 的初学者,你应该跳过__del__ 函数直到很久以后。真的很少需要。
  • 顺便说一下,你可能有兴趣阅读PEP 442: Safe Object Finalization

标签: python


【解决方案1】:

Python 3 docs 中,开发人员现在已经明确表示destructor 实际上并不是__del__ 方法的合适名称。

object.__del__(self)

在实例即将被销毁时调用。这也称为终结器或(不正确的)析构函数。

请注意,OLD Python 3 文档曾经暗示“析构函数”正确的名称:

object.__del__(self)

在实例即将被销毁时调用。这也称为析构函数。如果基类具有__del__() 方法,则派生类的__del__() 方法(如果有)必须显式调用它以确保正确删除实例的基类部分。

来自other answers,也来自Wikipedia

在具有自动垃圾回收机制的语言中,很难确定性地确保调用析构函数,因此这些语言通常被认为不适合 RAII [Resource Acquisition Is Initialization]

所以你几乎不应该实现__del__,但它让你有机会在一些(罕见的?)用例中这样做

【讨论】:

  • 一个用例是确保在对象被垃圾收集之前清理关键资源。 IE。在__del__中检查资源是否正常关闭,如果没有正常关闭并发出警告。
  • 鉴于__del__ 不是一个 C++ 风格的析构函数,并且 RAII 或多或少正是 Python 自动为您提供的,关于何时应该实现的最终结论__del__ 似乎与之前的不同。
【解决方案2】:

正如其他答案已经指出的那样,您可能不应该在 Python 中实现 __del__。如果你发现自己认为你真的需要一个析构函数(例如,如果你的类包装了一个需要显式关闭的资源),那么 Pythonic 的方法是使用context managers

【讨论】:

  • 上下文管理器链接很好,是否每个对象(包括用户类型)都实现了上下文管理器?
  • @Explorer_N 不,你需要自己做。而且它们也没有所有相同的语义。但这很容易做到。
  • @Explorer_N:虽然您通常需要自己为自定义类实现功能,但使用来自contextlib module 的帮助器通常非常容易。
【解决方案3】:

del真的是析构函数吗?

不,__del__ 方法不是析构函数,它只是一个普通的方法,你可以在你想要执行任何操作时调用它,但它总是在垃圾收集器销毁对象之前调用。 把它想象成一个干净或最后的方法。

【讨论】:

  • del 的调用是否会在必须发生时发生,或者就像我们在 java 中的 finalize() 一样,我听说一些参考 finalize() 调用是不可预测的
  • @Explorer_N,当对象即将被删除时,python解释器总会调用它。
【解决方案4】:

我今天才知道它是如此罕见(而且我很久以前就进入了 python)。

内存已被 GC 释放,文件已关闭,...但是你可能需要在课堂之外执行一些带有效果的任务。

我的用例是关于对一些临时目录实施某种 RAII。无论如何我都希望它被删除。

我没有在处理后将其删除(经过一些更改后不再运行),而是将其移至 __del__ 方法,它按预期工作。

这是一个非常特殊的情况,我们并不真正关心何时调用该方法,只要在离开程序之前调用它即可。所以,请谨慎使用。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 2011-12-13
  • 2019-06-21
  • 2012-12-22
  • 2020-04-12
  • 2017-09-27
  • 2015-12-09
相关资源
最近更新 更多