1

我发现__del__当涉及循环引用时,自定义方法似乎没有执行。

这是一个示例代码:

class DelClass():
        def __init__(self,a):
            self.prop = a 

        def __del__(self):
            print 'del'



if __name__ == "__main__":

    dc1 = DelClass(None)
    dc2 = DelClass(dc1)#dc2 referring to dc1
    dc1.prop = dc2#dc1 referring to dc2, thus creating circular reference
    del dc1#not executing the custom __del__ method

    dc = DelClass(1)
    del dc#executing the custom __del__ method

为什么会发生这种情况?

编辑: 感谢 BrenBarn。我找到了原因。

del something仅将引用计数减something1。

__del__只有当引用计数达到 0 时才会执行。

这是一个测试代码:

import gc

class DelClass():
    def __init__(self,name,a):
        self.name = name
        self.prop = a

    def __del__(self):
        print '#####deleting',self.name

dc1 = DelClass("dc1",None)
dc2 = DelClass("dc2",dc1)#dc2 referring to dc1
dc1.prop = dc2#dc1 referring to dc2, thus creating circular reference
print "before deleting dc1,reference count:",len(gc.get_referrers(dc1))
del dc1#not executing the custom __del__ method
print "after deleting dc1, reference count:",len(gc.get_referrers(dc2.prop))
print "deleting the reference held by dc2"
del dc2.prop
print dc2

输出是:

before deleting dc1,reference count: 2
after deleting dc1, reference count: 1
deleting the reference held by dc2
#####deleting dc1
<__main__.DelClass instance at 0x9316dec>
#####deleting dc2

又出现了一个问题:

为什么输出中的最后一行(#####deleting dc2)会发生?

发生了一些隐式del操作?

4

4 回答 4

3

阅读垃圾收集器文档__del__。 不会做你可能认为它会做的事情,. 在执行 a 时不一定会调用,并且在循环引用的情况下可能永远不会调用。所做的就是将引用计数减 1。__del__del__del__deldel

于 2012-06-05T04:47:57.370 回答
2

自 python 3.4 以来,这不再是真的。参见PEP-442

于 2016-02-26T16:49:28.080 回答
1

阅读此链接。我想这会对你有所帮助。

del不打电话__del__

del以您使用的方式删除局部变量。__del__当对象被销毁时调用。Python 作为一门语言不保证它什么时候会销毁一个对象。

----更新编辑----

回答Some implicit del operation happens?

阅读此链接将对您有所帮助

Python 不保证什么时候__del__被调用,或者它是否被调用。事实上,__del__如果对象是引用循环的一部分,则不太可能调用方法,因为即使整个循环被清理干净,Python 也无法决定在哪里中断循环以及__del__方法的顺序(如果有)应该被调用。由于__del__'s 相当古怪的语义(为了调用__del__对象的引用计数暂时增加,并且该__del__方法可以通过将引用存储在其他地方来防止对象的破坏),在其他实现中发生的事情有点废话。(我不记得当前 Jython 中的确切细节,但它在过去已经改变了几次。)

也就是说,在 CPython 中,如果__del__被调用,它会在引用计数降至零时立即调用(因为引用计数是__del__ 调用方法的唯一方式,而 CPython 调用的唯一机会__del__是在实际引用计数发生更改时。)

于 2012-06-05T05:25:34.910 回答
1

因为垃圾收集器无法知道哪个可以安全地先被删除。

于 2012-06-05T04:46:58.447 回答