作者:多米音乐_34306427 | 来源:互联网 | 2023-05-23 17:29
乍一看,Python的__del__
特殊方法似乎提供了析构函数在C++中具有的相同优势.但是根据Python文档(https://docs.python.org/3.4/reference/datamodel.html),无法保证您的对象的__del__
方法完全被调用!
无法保证__del__
在解释器退出时仍然存在的对象调用()方法.
换句话说,这个方法没用!不是吗?可能会或可能不会被调用的钩子函数确实没有多大好处,因此__del__
对RAII没有任何帮助.如果我有一些必要的清理,我不需要它运行一些时间,哦,当GC感觉它真的,我需要它可靠,确定和100%的时间运行.
我知道Python提供了上下文管理器,它对于该任务更有用,但为什么要__del__
保持原样呢?重点是什么?
1> Kevin..:
__del__
是终结者.它不是一个析构函数.终结者和破坏者是完全不同的动物.
可以可靠地调用析构函数,并且只存在具有确定性内存管理的语言(例如C++).Python的上下文管理器(with
语句)在某些情况下可以实现类似的效果.这些是可靠的,因为物体的寿命是精确固定的; 在C++中,对象在显式delete
d或者退出某个范围时(或者当智能指针为了响应自身的破坏而删除它们时)会死亡.这就是析构函数运行的时候.
终结器不能可靠地调用.终结器的唯一有效用途是作为紧急安全网(注意:本文是从.NET角度编写的,但概念转换得相当好).例如,返回的文件对象open()
在完成时自动关闭.但你仍然应该自己关闭它们(例如使用with
声明).这是因为垃圾收集器动态地销毁对象,垃圾收集器可能会立即运行,也可能不立即运行,并且通过分代垃圾收集,它可能会或可能不会收集任何给定传递中的某些对象.由于没有人知道我们将来可能会发明什么样的优化,因此最安全地假设您无法知道垃圾收集器何时会收集您的对象.这意味着你不能依赖终结者.
在CPython的特定情况下,由于使用引用计数(比垃圾收集更简单,更可预测),您可以得到更强的保证.如果您可以确保永远不会创建涉及给定对象的引用循环,则将在可预测的位置调用该对象的终结器(当最后一个引用死亡时).这是唯一的真正的CPython的,参考实现,而不是 PyPy,IronPython的,Jython的,或者任何其他的实现.
@fijal:从3.4+开始不再如此.参见PEP 442.此外,PyPy确实可以保证呼叫,但*不是在可预测的时间*,因此它不足以满足大多数目的.