python是否总是同步调用__del__?

时间:2012-12-03 19:19:35

标签: python

__del__的python文档解释了当引用计数减少到零时,可以调用对象的__del__方法。是否总是立即调用(即同步)?或者有可能在将来某个时候调用__del__方法吗?

此外,这个问题的答案一般适用于Python吗?或者是否为语言实现提供了一些自由度? (我使用CPython。)

对于这个问题,假设如下:

  • 有问题的对象继承自object
  • 相关对象具有自定义__del__实施。
  • 对象的自定义__del__实现不会创建对任何对象的新引用。
  • 有问题的对象不属于参考周期。
  • 口译员不在关闭过程中。

据我所知,这个话题似乎有很多混乱。为了避免不必要的讨论,我们举一些不可接受的答案:

  • “不要使用__del__!这令人困惑!”
  • “不要使用__del__!这不是'pythonic'。”
  • “请勿使用__del__,而是使用上下文管理器。”
  • 在没有引用可靠来源的情况下,对任何有或无保证的断言作出任何回答。 (请随意引用其他SO答案,但不要依赖它们作为您的唯一来源。“可信”在这种情况下意味着来自文档,信誉良好的人,甚至可能是CPython源本身。)

要使用示例重新解释此问题,请考虑以下代码:

class C(object):
    def __init__(self, i):
        self.i = i

    def __del__(self):
        print "C.__del__:", self.i

print "Creating list"
l = [C(0), C(1), C(2)]

print "Popping item 1"
l.pop(1)

print "Clearing list"
l = []

print "Exiting..."

产生以下输出:

$ python test_del.py
Creating list
Popping item 1
C.__del__: 1
Clearing list
C.__del__: 2
C.__del__: 0
Exiting...

请注意,在此示例中,同步调用__del__ 。这种行为是否由语言保证? (请记住上面列出的假设。)

2 个答案:

答案 0 :(得分:3)

来自Python语言参考(Python 2.7.3版),Chapter 3, Data model

  

永远不会明确销毁对象;然而,当它们变得无法到达时,它们可能被垃圾收集。允许实现推迟垃圾收集或完全省略它 - 实现垃圾收集的实现质量问题,只要没有收集到仍然可以访问的对象。

     
    

CPython实现细节:CPython目前使用引用计数方案和(可选)延迟检测循环链接垃圾,一旦它们无法访问就收集大多数对象,但不保证收集包含循环引用的垃圾。有关控制循环垃圾收集的信息,请参阅gc模块的文档。其他实现的行为不同,CPython可能会改变。当对象无法访问时,不要依赖于对象的立即终结(例如:总是关闭文件)。

  

答案 1 :(得分:1)

语言无法保证此行为。例如,请参阅PyPy's documentation on their garbage collection scheme,其中明确指出在PyPy中调用__del__的时间与CPython不同。

如果你的对象不是引用周期的一部分,那么我理解这种行为在CPython中是可靠的,但我不知道任何明确的保证。