当前位置: 首页 > 面试题库 >

为什么不能保证在解释器退出时调用析构函数?

卢枫涟
2023-03-14
问题内容

从python
docs

不能保证__del__()在解释器退出时为仍然存在的对象调用方法

为什么不?如果做出此保证会出现什么问题?


问题答案:

我不相信以前的答案在这里。

首先请注意,给出的示例 不会 阻止__del__在退出过程中调用方法。实际上,当前的CPython
调用__del__给定的方法,在Python 2.7中两次,在Python 3.4中一次。因此,这不能成为显示为什么不做出保证的“杀手example”。

我认为文档中的声明并非出于设计原则,即调用析构函数将是不好的。尤其重要的是,似乎在CPython
3.4及更高版本中,它们总是像您期望的那样被调用,并且此警告似乎没有意义。

相反,我认为该语句只是反映了一个事实,即CPython实现有时并未在退出时调用所有析构函数(大概是出于易于实现的原因)。

情况似乎是CPython 3.4和3.5确实总是在解释器出口调用所有析构函数。

相比之下,CPython
2.7并不总是这样做。当然,__del__在具有循环引用的对象上通常不会调用方法,因为如果这些对象具有__del__方法,则无法将其删除。垃圾收集器不会收集它们。尽管在解释器退出时对象确实消失了(当然),它们没有被终结,所以__del__从不调用它们的方法。在执行PEP
442之后,在Python 3.4中不再是这样。

但是,似乎Python 2.7也不会最终确定具有循环引用的对象,即使它们没有析构函数,即使它们仅在解释器退出期间变得不可访问也是如此。

大概这种行为是非常特殊的,很难解释,就像文档一样,最好仅通过通用免责声明来表达。

这是一个例子:

class Foo(object):
    def __init__(self):
        print("Foo init running")

    def __del__(self):
        print("Destructor Foo")

class Bar(object):
    def __init__(self):
        print("Bar1 init running")
        self.bar = self
        self.foo = Foo()

b = Bar()

# del b

随着del b注释掉,在析构函数Foo是不是在Python 2.7叫虽然它是在Python 3.4。

随着del b加入,然后调用析构函数(在解释退出)在这两种情况下。



 类似资料:
  • 基本问题:程序何时在C中调用类的析构函数方法?有人告诉我,每当对象超出范围或受到时都会调用它 更具体的问题: 1)如果对象是通过指针创建的,并且该指针后来被删除或给定一个新的地址来指向,它所指向的对象是否调用其析构函数(假设没有其他东西指向它)? 2) 接下来是问题1,什么定义了对象何时超出范围(与对象何时离开给定的{block}无关)。换句话说,什么时候对链表中的对象调用析构函数? 3) 你想手

  • 在C中,您可以将许多内容声明为:变量、函数(包括成员函数和运算符)、构造函数,以及从C 1z开始的语句和lambda表达式。但是,声明析构函数会导致错误: 我的问题: 为什么不能将析构函数标记为constexpr 如果我没有提供析构函数,那么隐式生成的析构函数是constexpr吗 如果我声明一个默认析构函数(

  • 问题内容: 这可能是一个愚蠢的问题,但是我正在测试我对Python的一些假设,并对为什么以下代码段在线程中调用时不退出而在主线程中调用时退出而感到困惑。 sys.exit()的文档指出,该调用应从Python退出。从该程序的输出中可以看到,“ post thread exit”从不打印,但是即使在线程调用退出之后,主线程仍继续运行。 是否为每个线程创建了一个单独的解释器实例,并且对exit()的调

  • 问题内容: 有谁知道为什么可以使用或而不是非静态方法在构造函数的第一行中引用方法? 考虑以下工作: 以及以下非工作示例: 问题答案: 非静态方法是实例方法。这只能在现有实例中访问,并且在构造函数中时实例尚不存在(它仍在构建中)。 为什么会这样呢?因为实例方法可以访问实例(非静态)字段,该字段在不同实例中可以具有不同的值,所以在现有的已完成实例之外的其他地方调用这种方法没有任何意义。

  • 为什么在第一次迭代后不停止脚本? 在我看来,它必须在第一次迭代之后停止。

  • 问题内容: 这是我的代码: 当我执行此操作时,将引发错误: 我确保它不是拼写错误,并且我没有拼错该函数的名称,所以为什么会出现NameError? 问题答案: 除非已定义函数,否则无法调用它。将块移动到文件的顶部,在导入的下面。 某些语言允许您在定义函数之前使用函数。例如,javascript将其称为“吊装”。但是Python并不是这些语言之一。 请注意,只要按 时间顺序 在使用前定义,就可以在比