最近,我对python的内存管理感到困惑。首先是关于dict,说我有 复合词典对象,如
d = {id1: {'x': 'a', 'y': [1,2,3], 'z': {'k', 'v'}}, id2: {...}}
如果我打电话给del,
del d[id1]
d [id1] ['y']和d [id1] ['z']会一起回收吗?
第二个是列表,我从here读了答案,所以我试了一下。这是我的代码
import sys
import gc
import time
from collections import defaultdict
from pprint import pprint
def f():
d = defaultdict(int)
objects = gc.get_objects()
for o in objects:
d[type(o)] += 1
x = d.items()
x = sorted(x, key=lambda i: i[1], reverse=True)
pprint(x[:5])
def loop():
while True:
leaked = [[x] for x in range(100)]
f()
time.sleep(0.1)
当范围是100时,功能f确实显示我的列表正在增加,但是当时 我将范围修改为1000,没有任何改变,列表的数量保持不变。 任何人都可以告诉我这是什么问题?
答案 0 :(得分:5)
del
删除对当前命名空间中对象的引用。 在Cpython 中,当一个对象的引用计数达到0时,它将可供python用于将来的对象(它不一定会回到操作系统)。
考虑:
a = []
b = a
del a #The list doesn't get freed because `b` is still a reference to that list
在您的方案中,当您del d[id1]
时,删除对该(内部)词典的引用。由于它持有一堆对其他对象的引用,因此每个对象现在少了1个引用。如果它们的引用计数达到0,它们将被收集,并且它们持有引用的每个对象都将减少其引用计数等等。
答案 1 :(得分:1)
“d [id1] ['y']和d [id1] ['z']会一起回收吗?”
假设没有其他任何内容引用该字典或其内容,那么它全部同时进入引用计数0。但是,不能保证立即收集任何内容。
“......任何人都可以告诉我这是什么问题?”
Python缓存低整数对象,因此它们将始终被引用:
http://docs.python.org/2/c-api/int.html - “当前实现为-5到256之间的所有整数保留一个整数对象数组,当你在该范围内创建一个int时,实际上只返回对现有对象的引用。” / p>
这可以解释你所看到的行为。而不是在范围(100)中使用x,创建匿名对象,例如
leaked = [object() for x in range(100)]