在测试一个包含弱引用的类时,我偶然发现了这个有点奇怪的行为:Python垃圾收集器似乎缺少列表中的最后一个元素。一个最小的例子:
class Test(object):
def __init__(self, i):
self.i = i
def __del__(self):
print('Deleting Test {0}'.format(self.i))
if __name__ == '__main__':
x = [Test(i) for i in range(5)]
for t in x:
print(t.i)
x = []
以上将打印:
0
1
2
3
4
删除测试3
删除测试2
删除测试1
删除测试0
无论创建对象列表(10,100,1000等)的大小如何,都会发生这种情况。为了仔细检查是否是这种情况,我尝试强制进行垃圾收集,并确保在将原始列表设置为{后仍然可以使用对原始列表值的弱引用(并且未标记为已死) {1}}或致电[]
:
del x
此外,尝试创建一个大型列表(再次)强制垃圾收集什么都不做;例如,在上面的import weakref
import gc
z = None
if __name__ == '__main__':
x = [Test(i) for i in range(5)]
for t in x:
print(t.i)
z = weakref.ref(x[4])
x = []
gc.collect(2)
print(z().i)
和x = []
之间插入以下内容:
gc.collect(2)
这在Python 2.7.6和3.3.3上都会发生。我意识到垃圾收集是非确定性的,但这似乎相当可疑。有没有特定的原因,最后一个元素没有被垃圾收集,或者这是一种一个一个一个错误的错误?
答案 0 :(得分:5)
您的第一个源代码中的变量t
仍然存在,并保存对最后一个条目的引用。致电del t
后,最后Test
个对象将被删除。