即使gc被禁用,为什么python会收集?

时间:2013-07-24 11:26:41

标签: python garbage-collection

此代码

import gc
gc.disable()
print gc.isenabled()
print len(gc.get_objects())
class Foo(): pass
print len(gc.get_objects())

a=[]
print len(gc.get_objects())
for i in xrange(10000):
    a.append(Foo())

print len(gc.get_objects())
a=[] # Should not collect
print len(gc.get_objects())
gc.collect()
print len(gc.get_objects())

生成此输出

False
3754
3755
3756
13756
3756
3374

我希望倒数第二个数字为13756,因为gc已被禁用,当原始a列表超出范围时,它不应删除这些对象。显然python正在收集这些对象。为什么?

python是2.7.2

1 个答案:

答案 0 :(得分:2)

因为垃圾收集只处理循环引用。引自gc module documention

  

由于收集器补充了Python中已经使用的引用计数,因此如果您确定程序没有创建引用循环,则可以禁用收集器。

CPython使用引用计数来清理大多数对象。当您使用空列表替换引用的列表a时,旧列表的引用计数将降为0,因此在该点将其删除。删除列表会导致Foo()实例的引用计数也降至0,等等。

如果您改为创建循环引用,禁用垃圾回收,您将看到数字保持不变:

class Foo(object):
    def __init__(self):
         self.bar = Bar(self)

class Bar(object):
    def __init__(self, foo):
        self.foo = foo