举个例子:
>>> import gc
>>> d = { 1 : object() }
>>> gc.get_referrers(d[1])
[] # Python 2.7
[{1: <object object at 0x003A0468>}] # Python 2.5
为什么 d
未被列为对象的引用者?
EDIT1:虽然d中的dict引用了该对象,为什么没有列出dictionairy?
答案 0 :(得分:5)
doc提及:
此功能仅定位那些支持垃圾的容器 采集;扩展类型,它引用其他对象但不引用 支持垃圾收集将无法找到。
似乎字典不支持它。
这就是为什么:
垃圾收集器试图避免跟踪简单的容器 不能成为一个循环的一部分。在Python 2.7中,现在对于元组来说是正确的 和dicts包含原子类型(如整数,字符串等)。 传递上,包含原子类型元组的dict不会 追踪。这有助于降低每次垃圾回收的成本 通过减少要考虑和遍历的对象数量 收藏家。
似乎object()
被认为是原子类型,并且尝试使用用户定义类的实例(即不是object
)将此确认为你的代码现在有效。
# Python 2.7
>>> class A(object): pass
>>> r = A()
>>> d = {1: r}
>>> del r
>>> gc.get_referrers(d[1])
[{1: <__main__.A instance at 0x0000000002663708>}]
另见issue 4688 。
答案 1 :(得分:1)
这是对Python 2.7中对象跟踪方式的改变;仅包含原子类型(包括object()
的实例)的元组和字典(不再需要循环中断)不再列出。
见http://bugs.python.org/issue4688;这是为了避免在创建元组或字典的负载时出现性能问题。
解决方法是在 需要跟踪的词典中添加一个对象:
>>> gc.is_tracked(d)
False
>>> class Foo(object): pass
...
>>> d['_'] = Foo()
>>> gc.is_tracked(d)
True
>>> d in gc.get_referrers(r)
True
一旦跟踪,字典只会在gc收集周期后回到未跟踪状态:
>>> del d['_']
>>> gc.is_tracked(d)
True
>>> d in gc.get_referrers(r)
True
>>> gc.collect()
0
>>> gc.is_tracked(d)
False
>>> d in gc.get_referrers(r)
False