在这种情况下,您实际上得到了内存使用的不完整图片。字典的总大小会不定期地增加一倍以上,如果您比较字典大小增加后这两个结构的大小,那么它又会更大。一个具有递归大小函数的简单脚本(请参见下面的代码)显示出了一个相当清晰的模式:
i: 2 list size: 296 dict size: 328 difference: -32
i: 3 list size: 392 dict size: 352 difference: 40
i: 4 list size: 488 dict size: 376 difference: 112
i: 5 list size: 616 dict size: 400 difference: 216
i: 7 list size: 808 dict size: 1216 difference: -408
i: 10 list size: 1160 dict size: 1288 difference: -128
i: 13 list size: 1448 dict size: 1360 difference: 88
i: 17 list size: 1904 dict size: 1456 difference: 448
i: 23 list size: 2480 dict size: 3904 difference: -1424
i: 31 list size: 3328 dict size: 4096 difference: -768
i: 42 list size: 4472 dict size: 4360 difference: 112
i: 56 list size: 5912 dict size: 4696 difference: 1216
i: 74 list size: 7880 dict size: 5128 difference: 2752
i: 100 list size: 10520 dict size: 14968 difference: -4448
i: 133 list size: 14024 dict size: 15760 difference: -1736
i: 177 list size: 18672 dict size: 16816 difference: 1856
当 i
增大时,这种模式会继续下去。 (您可以使用自己的方法测试此内容-尝试将 i
设置在接近 2636744
的位置。该字典的大小在那一点上更大,至少对我来说是这样。)Martijn 是正确的,元组列表中的元组会增加内存开销,抵消了列表比字典更具有内存优势的优势。 但结果平均而言,并不是字典更好;它只是与字典相似。因此,针对您最初的问题:
当您想要在内存中存储大量键值数据时,哪种数据结构更节省内存,字典还是元组列表?
如果您所关心的仅仅是内存,那么实际上并没有什么影响。
然而,请注意,遍历字典通常比遍历列表略慢,因为无法避免遍历字典中所有空桶。因此存在一些权衡 - 字典用于随机键查找(快得多),但列表在迭代时速度(稍微)更快。字典大多数情况下可能会更好,但在一些罕见情况下,列表可能提供微小的优化。
以下是测试大小的代码。它可能无法为所有边缘情况生成正确结果,但对于像这样的简单结构,它应该没有任何问题。(但如果您遇到任何问题,请让我知道。)
import sys, collections, itertools, math
def totalsize(x):
seen = set()
return ts_rec(x, seen)
def ts_rec(x, seen):
if id(x) in seen:
return 0
else:
seen.add(id(x))
x_size = sys.getsizeof(x)
if isinstance(x, collections.Mapping):
kv_chain = itertools.chain.from_iterable(x.iteritems())
return x_size + sum(ts_rec(i, seen) for i in kv_chain)
elif isinstance(x, collections.Sequence):
return x_size + sum(ts_rec(i, seen) for i in x)
else:
return x_size
for i in (10 ** (e / 8.0) for e in range(3, 19)):
i = int(i)
lsize = totalsize([(x, x) for x in xrange(i)])
dsize = totalsize(dict((x, x) for x in xrange(i)))
print "i: ", i,
print " list size: ", lsize, " dict size: ", dsize,
print " difference: ", lsize - dsize