Python:破解gc之谜

Python:破解gc之谜,python,garbage-collection,python-2.6,Python,Garbage Collection,Python 2.6,我试图理解gc,因为我在一个程序中有一个很大的列表,我需要删除它以释放一些急需的内存。我想回答的基本问题是如何找到gc跟踪的内容和释放的内容?下面是说明我的问题的代码 import gc old=gc.get_objects() a=1 new=gc.get_objects() b=[e for e in new if e not in old] print "Problem 1: len(new)-len(old)>1 :", len(new), len(old) print "Prob

我试图理解gc,因为我在一个程序中有一个很大的列表,我需要删除它以释放一些急需的内存。我想回答的基本问题是
如何找到gc跟踪的内容和释放的内容?
下面是说明我的问题的代码

import gc
old=gc.get_objects()
a=1
new=gc.get_objects()
b=[e for e in new if e not in old]
print "Problem 1: len(new)-len(old)>1 :", len(new), len(old)
print "Problem 2: none of the element in b contain a or id(a): ", a in b, id(a) in b
print "Problem 3: The reference counts are insanely high, WHY?? "
我知道这是一种奇怪的行为,但在本手册中没有提到。首先,为什么分配一个变量会为gc创建多个条目?为什么它们都不是我做的变量??其中是我在get_objects()中创建的变量的条目

编辑:作为对martjin第一次回复的回应,我检查了以下内容

a="foo"
print a in gc.get_objects()

仍然不行:(我如何检查gc是否正在跟踪a?

gc.get\u objects()的结果本身没有被跟踪;否则它将创建一个循环引用:

>>> import gc
>>> print gc.get_objects.__doc__
get_objects() -> [...]

Return a list of objects tracked by the collector (excluding the list
returned).
您没有看到列出的
a
,因为它引用了一个低整数单例。Python对-5到256之间的值重新使用同一组
int
对象。因此,
a=1
不会创建要跟踪的新对象。您也不会看到任何其他基元类型

CPython垃圾收集只需要跟踪容器类型,这些类型可以引用其他值,因为GC需要做的唯一事情就是打破循环引用


请注意,当任何Python脚本启动时,已经运行了一些自动代码。
site.py
设置了Python路径,例如,它涉及列表、映射等。然后是上面提到的已记忆的
int
值,CPython还缓存
tuple()
可重复使用的对象等。因此,在启动时,Easy 5k+对象在代码的一行开始之前就已经处于活动状态。

@Martjin:感谢您的回复,我又添加了一个示例来澄清问题仍然存在occurs@pushpen:小字符串也被插入。使用自定义类和实例:
class Foo:pass
然后在gc.get\u objects()和@MartijnPieters中使用
foo=foo()
foo,这将解释在以后引入字符串时,
gc.get\u objects()
是否不会增长。但是字符串根本不在列表中,如果在获取第一个对象列表后引入字符串文字,列表也不会改变(例如,使用REPL)。这是因为循环GC有一个优化,不跟踪不能成为循环一部分的对象(包括int、float、字符串,有时甚至是此类类型的列表)。在
GC.get_objects()中从来没有
str
,当然它可能包含本身引用字符串的对象。@delnan:我得出了相同的结论;刚刚找到了确认,并回忆了为什么它也这么做。顺便说一句,你为什么不存在
a
的推理也有同样的缺陷:如果可能出现整数,缓存应该只影响整数是否出现多次,而不是它是否发生。同样的解决方案适用。