首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >终结器方法被调用多少次和僵尸(PEP 442)

终结器方法被调用多少次和僵尸(PEP 442)
EN

Stack Overflow用户
提问于 2014-07-14 11:07:36
回答 2查看 294关注 0票数 7

我对终结器方法__del__产生了怀疑。

__del__方法是在清理对象之前调用的,但是这个方法甚至可以使对象复活。现在我注意到,在Python2.7中,每次对象的引用计数器下降为零(即使对象已经复活)时,终结器就被称为零(即使对象已经复活),在Python3.4中,它在对象的整个生命周期中只被调用一次,所以如果它被复活,然后它的计数器降到零,终结器方法就不再被调用了。

我从佩普442上读到,在python3.4中,这种选择是为了防止僵尸复活:

但是,如果对象已经完成,则不会调用终结器。这阻止了我们最后确定僵尸

我的怀疑是,我不知道这个解决方案如何可以阻止我们最后确定僵尸,你能给我一些具体的例子吗?此外,对象只能复活一次。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-14 11:57:51

假设我们有以下类:

代码语言:javascript
复制
class RefCycle:
    def __init__(self):
        self.refcycle = self
    def __del__(self):
        print('finalizing')
        print(self.refcycle)

我们创建并收集一个循环隔离:

代码语言:javascript
复制
RefCycle()
import gc
gc.collect()

当垃圾收集器检测到循环隔离时,它会调用RefCycle实例的终结器。然后,它开始破坏引用。当它清除self.refcycle属性时,对象的折算下降到0。

这是重要的是,最终的对象不被重新化。如果没有“已经确定”的标志,则对象将因被重新计算到0而被重新化。由于垃圾收集器已经处理了对象的属性,这将是一件非常糟糕的事情。“已经确定”的标志保护我们不受这种情况的影响。

票数 1
EN

Stack Overflow用户

发布于 2014-07-14 12:00:31

我想我找到了一个理由,但如果不是正确的话,就帮帮我吧。

继PEP 442之后,CI的处理传统上是这样运作的:

  1. 对CI对象的Weakrefs被清除,并调用它们的回调。此时,这些对象仍然可以安全使用。
  2. CI成为一个CT,因为GC系统地破坏了它内部的所有已知引用(使用tp_clear函数)。
  3. 没什么。所有CT对象都应该在步骤2中被处理(作为清除引用的副作用);这个集合已经完成。

新提案的内容如下:

  1. 对CI对象的Weakrefs被清除,并调用它们的回调。此时,这些对象仍然可以安全使用。
  2. 所有CI对象的终结器称为.
  3. 再次遍历CI以确定它是否仍然是孤立的。如果确定CI中至少有一个对象现在可以从CI外部到达,则此集合被中止,整个CI被复活。否则,继续.
  4. CI成为一个CT,因为GC系统地破坏了它内部的所有已知引用(使用tp_clear函数)。
  5. 没什么。所有CT对象都应该在步骤4中被处理(作为清除引用的副作用);这个集合已经完成。

所以你可以看到,前者的第2步和后者的第4步是相同的,特别是它们使用相同的函数tp_clear,现在(在这里帮助我,因为我没有读过代码,我不太适合读C代码)这个函数,从我在销毁一个对象之前推导出来的,叫做终结器,但是因为它已经被调用了,CI可以开始一个CT,并且复活一个僵尸将是一个错误,终结器只被称为一次。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24735187

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档