# -*- coding: utf-8 -*-
class tA():
def __init__(self):
print 'AAA'
def __del__(self):
print 'BBB'
class tC(tA):
def __init__(self, a, b=0):
tA.__init__(self)
self.b=b # 1. del this ok
class tD(tC):
def __init__(self):
a=1
#tC.__init__(self, a) # 2. use this ok
tC.__init__(self, a, self.func) # 3. use this not ok
#tC.__init__(self, a, 3) # 4. use this ok
def func(self, pos):
pass
if __name__ == '__main__':
tD()
为什么没有“BBB”输出?你知道吗
如果我del zhe#1,输出是正常的
如果使用#2或#4,则输出正常
如果使用#3,则输出没有“BBB”?你知道吗
因为
'BBB'
是用类的终结器(__del__
函数)打印的。垃圾收集器收集对象时,将运行终结器和终结器。你知道吗Python对垃圾收集使用双重策略:引用计数和循环检测。引用计数达到0的对象将被立即收集,但如果它们参与循环,则它们的计数将永远不会达到0。然后定期调用GC循环检测例程,最终将检测到它并释放所有悬空对象。你知道吗
在您的特定代码中,case#3创建了一个引用循环:
self.b
是对self.func
的引用。但是GC循环检测永远不会运行,因为程序在有机会之前就结束了。你知道吗但是,即使GC运行,带有终结器的对象也有特殊的规则。从documentation:
另外,从here
因此,在3.4之前的Python中,在带有终结器的类中,您必须手动中断周期:
因为
func
是一个绑定方法,因此间接引用它绑定到的对象,这意味着您正在创建一个引用循环。你知道吗您可以通过执行以下操作来验证这一点:
在您的案例2和案例4中应该打印
1
,在案例3中应该打印2
。你知道吗^{} 的文档中有一个关于引用循环的注释:
基本上,这意味着如果您有一个
__del__
方法,它将阻止清理包含引用循环的对象。你知道吗相关问题 更多 >
编程相关推荐