乍一看,好像是Python的__del__
特殊方法提供了与 C++ 中析构函数几乎相同的优点。但根据Python文档(https://docs.python.org/3.4/reference/datamodel.html https://docs.python.org/3.4/reference/datamodel.html), 有没有保证你的对象是__del__
方法根本不会被调用!
不保证__del__
() 方法是为解释器退出时仍然存在的对象调用的。
那么也就是说,这个方法是没有用的!不是吗?一个可能被调用也可能不会被调用的钩子函数确实没有多大用处,所以__del__
没有提供任何有关 RAII 的信息。如果我有一些必要的清理工作,我不需要它来运行一些时间,哦,每当 GC 感觉真的如此时,我就需要它运行可靠、确定且 100% 成功.
我知道 Python 提供了上下文管理器,这对于该任务来说更有用,但为什么__del__
留在身边吗?重点是什么?
__del__
是一个终结器。它不是析构函数。终结器和析构器是完全不同的动物。
析构函数被可靠地调用,并且仅存在于具有确定性内存管理的语言(例如 C++)中。 Python 的上下文管理器(with
声明)在某些情况下可以达到类似的效果。这些是可靠的,因为物体的寿命是精确固定的;在 C++ 中,对象在显式声明时就会消亡delete
d 或者当退出某个作用域时(或者当智能指针响应其自身的破坏而删除它们时)。这就是析构函数运行的时候。
终结器未被可靠地调用。终结器的唯一有效用途是紧急安全网 https://blogs.msdn.microsoft.com/oldnewthing/20100809-00/?p=13203(注意:本文是从 .NET 角度编写的,但概念翻译得相当好)。例如,返回的文件对象open()
完成后自动关闭。但你仍然应该自己关闭它们(例如使用with
陈述)。这是因为对象是由垃圾收集器动态销毁的,垃圾收集器可能会也可能不会立即运行,并且通过分代垃圾收集,它可能会也可能不会在任何给定的传递中收集某些对象。由于没有人知道我们将来可能会发明什么样的优化,因此最安全的假设是您无法知道垃圾收集器何时会收集您的对象。这意味着您不能依赖终结器。
在 CPython 的特定情况下,由于使用了引用计数(这比垃圾收集更简单且更可预测),您可以获得稍微更强的保证。如果您可以确保永远不会创建涉及给定对象的引用循环,则该对象的终结器将在可预测的点(当最后一个引用消失时)被调用。这是onlyCPython 的真实情况,参考实现,以及notPyPy、IronPython、Jython 或任何其他实现的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)