在__del__中关闭/处理对象真的可以吗?

Arl*_*ren 7 python

我一直在考虑如何用Python编写类.更具体地说,如何实现构造函数以及如何销毁对象.我不想依靠CPython的引用计数来进行对象清理.这基本上告诉我应该使用with语句来管理我的对象生命周期,并且我需要一个显式的close/dispose方法(__exit__如果对象也是一个上下文管理器,则可以调用此方法).

class Foo(object):
    def __init__(self):
        pass
    def close(self):
        pass
Run Code Online (Sandbox Code Playgroud)

现在,如果我的所有对象都以这种方式运行,并且我的所有代码都使用语句或显式调用close()(或dispose())我不会真正看到我需要放入任何代码__del__.我们真的应该__del__用来处理我们的物品吗?

Len*_*bro 14

简答:不.

答案__del__很长:使用很棘手,主要是因为它不能保证被调用.这意味着你不能做那些绝对必须做的事情.这反过来意味着__del__基本上只能用于迟早会发生的清理,比如清理进程退出时要清理的资源,所以如果__del__不调用则无关紧要.当然,这些通常与Python将为您做的事情相同.所以这有点__del__无用.

此外,__del__当Python垃圾收集时调用,并且您不想等待Pythons垃圾收集,这意味着您__del__无论如何都无法使用.

所以,不要使用__del__.请__enter__/__exit__改用.

仅供参考:以下是非循环情况的示例,其中析构函数未被调用:

class A(object):
    def __init__(self):
        print('Constructing A')

    def __del__(self):
        print('Destructing A')

class B(object):
    a = A()
Run Code Online (Sandbox Code Playgroud)

好的,所以它是一个类属性.显然这是一个特例.但它只是表明确保__del__被调用并不是直截了当的.我很确定我已经看到了更多非循环的情况,其中__del__没有被调用.


ars*_*ars 8

不必要.有循环引用时会遇到问题.Eli Bendersky在他的博客文章中做了很好的解释: