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

2024-12-05 08:37:00
admin
原创
131
摘要:问题描述:我看到一个类中定义了一个__del__方法。此方法用于销毁类的一个实例。但是,我找不到使用这个方法的地方。这个方法如何使用?就像这样:obj1.del()?。我该如何调用该__del__方法?解决方案 1:__del__是一个finalizer 。当一个对象被垃圾回收时,它会被调用,而垃圾回收发生在...

问题描述:

我看到一个类中定义了一个__del__方法。此方法用于销毁类的一个实例。但是,我找不到使用这个方法的地方。这个方法如何使用?就像这样:obj1.del()?。

我该如何调用该__del__方法?


解决方案 1:

__del__是一个finalizer 。当一个对象被垃圾回收时,它会被调用,而垃圾回收发生在对该对象的所有引用都被删除之后的某个时刻。

简单情况下,这可能发生在您说完之后del x,或者,如果x是局部变量,则发生在函数结束后。特别是,除非存在循环引用,否则 CPython(标准 Python 实现)将立即进行垃圾收集。*

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

更有甚者,变量可以因多种原因而存在很长时间,例如传播异常或模块自省可以使变量引用计数大于 0。此外,变量可以是引用循环的一部分- 启用垃圾收集的 CPython 会中断大多数(但不是全部)这样的循环,而且即使中断也只是定期中断。

由于无法保证它会被执行,因此永远不要将需要运行的代码放入其中__del__()— 相反,此代码属于语句finally的子句try或语句中的上下文管理器with。但是,有一些有效的用例__del__例如,如果一个对象X引用Y并且还在Y全局cachecache['X -> Y'] = Y)中保留引用的副本,那么X.__del__删除缓存条目也是礼貌的。

如果您知道析构函数提供了(违反上述准则)必需的清理,您可能希望直接调用它,因为它作为一种方法没有什么特别之处:x.__del__()。显然,只有在您知道它可以被调用两次时才应该这样做。或者,作为最后的手段,您可以使用以下方法重新定义此方法

type(x).__del__ = my_safe_cleanup_method

*参考:

CPython 实现细节: CPython 当前使用引用计数方案,并带有(可选)循环链接垃圾的延迟检测,当大多数对象变得无法访问时,它会立即收集它们 [...] 其他实现的行为有所不同,并且 CPython 可能会发生变化。

解决方案 2:

我写下了另一个问题的答案,但这个问题更为准确。

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

这是一个略带主观性的回答。

不要使用__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- del -is-not-the-opposite-of- init /了解解释和陷阱。

  • __del__在 Python 中, sys.exit() 并不是一个“深受喜爱”的孩子。您会注意到, sys.exit() 文档并未指定在退出前是否收集垃圾,并且存在许多奇怪的问题。__del__在全局变量上调用 会导致奇怪的排序问题,例如http://bugs.python.org/issue5099__del__即使__init__失败也应该调用吗?请参阅http://mail.python.org/pipermail/python-dev/2000-March/thread.html#2423以获取长线程。

但另一方面:

以及我个人不喜欢该功能的原因__del__

  • 每次有人提起__del__它,它就会演变成三十条令人困惑的信息。

  • 它打破了 Python 之禅的这些原则:

+ 简单比复杂好。
+ 特殊情况还不足以特殊到打破规则。
+ 错误不应该悄无声息地发生。
+ 面对模糊性,拒绝猜测的诱惑。
+ 应该有一种(最好只有一种)明显的方法来做到这一点。
+ 如果实施起来很难解释,那就是一个坏主意。

因此,找一个不使用的理由__del__

解决方案 3:

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

del obj

原因是del引用计数仅减少一。如果其他对象引用了该对象,__del__则不会被调用。

不过,使用时有一些注意事项__del__。一般来说,它们通常不是很有用。在我看来,你更想使用 close 方法或with 语句。

请参阅有关方法的Python 文档__del__

还有一点需要注意: __del__如果过度使用方法,可能会抑制垃圾收集。特别是,具有多个带有方法的对象的循环引用不会被垃圾收集。这是因为垃圾收集器不知道先调用哪一个。有关更多信息,请参阅gc 模块__del__的文档。

解决方案 4:

__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
>>>   

请注意,jython 和 ironpython 对于何时删除和__del__调用对象有不同的规则。__del__但由于这一点以及调用对象时对象及其环境可能处于未知状态,因此不认为这是一种好的做法。也不能绝对保证__del__一定会被调用 - 解释器可以以各种方式退出而不删除所有对象。

解决方案 5:

如前所述,该__del__功能有些不可靠。在可能有用的情况下,请考虑使用__enter____exit__方法。这将提供类似于用于访问文件的语法的行为with open() as f: pass__enter__在进入范围时会自动调用with,而在退出时会自动调用。有关更多详细信息,__exit__请参阅此问题。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用