如何确保 __del__ 函数像通常(但不正确)预期的那样在 Python 类上调用? [英] How to ensure the __del__ function is called on a Python class as is commonly (but incorrectly) expected?

查看:35
本文介绍了如何确保 __del__ 函数像通常(但不正确)预期的那样在 Python 类上调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解 Python 类的 __del__ 函数 没有像许多人期望的那样处理:作为析构函数.

I understand that the __del__ function of a Python class is not treated in the way that many people might expect: as a destructor.

我也知道有更多pythonic"和可以说更优雅的整理方式,特别是使用 withconstruct.

I also understand that there are more 'pythonic' and arguably more elegant ways to tidy up, particularly with use of the with construct.

然而,当编写可能被不太熟悉 Pythonic 方式的观众使用的代码时,当清理很重要时,是否有一种优雅的方式可以让 __del__ 可靠地作为析构函数工作,不干扰 python 对 __del__ 的自然使用?

However, when writing code that may be used by an audience less versed in pythonic ways, when cleanup is important, is there an elegant way I can simply get __del__ to work as a destructor reliably, without interfering with python's natural use of __del__?

期望 __del__ 表现为析构函数似乎并不不合理,同时也很普遍.所以我只是想知道是否有一种优雅的方式让它按照预期工作 - 无视关于它是多么pythonic 的优点的许多争论.

The expectation that __del__ behave as a destructor doesn't seem unreasonable and at the same time is quite common. So I'm simply wondering if there is an elegant way to make it work as per that expectation - disregarding the many debates that can be had over the merits of how pythonic it is.

推荐答案

如果你理解了所有这些,为什么不以 Pythonic 的方式来做呢?比较另一个清理很重要的类:tempfile.TemporaryDirectory.

If you understand all that, why not do it in the Pythonic way? Compare another class where cleanup is important: tempfile.TemporaryDirectory.

with TemporaryDirectory() as tmp:
    # ...
# tmp is deleted

def foo():
    tmp = TemporaryDirectory()
foo()
# tmp is deleted

他们是怎么做到的?这是相关的部分:

How do they do this? Here's the relevant bit:

import weakref
class Foo():
    def __init__(self, name):
        self.name = name
        self._finalizer = weakref.finalize(self, self._cleanup, self.name)
        print("%s reporting for duty!" % name)

    @classmethod
    def _cleanup(cls, name):
        print("%s feels forgotten! Bye!" % name)

    def cleanup(self):
        if self._finalizer.detach():
            print("%s told to go away! Bye!" % self.name)

def foo():
    print("Calling Arnold")
    tmpfoo = Foo("Arnold")
    print("Finishing with Arnold")

foo()
# => Calling Arnold
# => Arnold reporting for duty
# => Finishing with Arnold
# => Arnold feels forgotten. Bye!

def bar():
    print("Calling Rocky")
    tmpbar = Foo("Rocky")
    tmpbar.cleanup()
    print("Finishing with Rocky")

bar()
# => Calling Rocky
# => Rocky reporting for duty!
# => Rocky told to go away! Bye!
# => Finishing with Rocky

weakref.finalize 将在对象被垃圾收集时触发 _cleanup ,或者在程序结束时(如果它仍然存在).我们可以保留终结器,以便我们可以显式地终止对象(使用 detach)并将其标记为死亡,这样终结器就不会被调用(当我们想要手动处理清理时).

weakref.finalize will trigger _cleanup when the object is garbage-collected, or at the end of the program if it's still around. We can keep the finaliser around so that we can explicitly kill the object (using detach) and mark it as dead so the finaliser is not called (when we want to manually handle the cleanup).

如果你想支持with的context用法,添加__enter____exit__方法很简单,只需要调用__exit__ 中的清理(上面讨论的手动清理").

If you want to support the context usage with with, it is trivial to add __enter__ and __exit__ methods, just invoke cleanup in __exit__ ("manual cleanup" as discussed above).

这篇关于如何确保 __del__ 函数像通常(但不正确)预期的那样在 Python 类上调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆