Python中字典的最大大小是多少?
我在用一个字典来存放很多对象,每个对象都有一个字符串名字。具体来说,这就是我的代码:
from itertools import product
for (i,j,k) in product(range(N),range(M),range(K)):
var_name='x_'+'_'+str(i)+str(j)+'_'+str(k)
var_dict[var_name] = f(var_name,other_params)
print len(var_dict)
f(...)
这个函数会返回一个对象。在我的代码中,N=363,M=500,K=2。所以我预计字典里会有363000个条目。但是当我检查 var_dict
的长度时,发现只有330860个!
(Pdb) len(var_dict)
330860
我有以下几个问题:
这有什么解释吗?比如说,Python内置的哈希表对可以存放的项目数量有没有限制?
我该怎么做才能解决这个问题?
4 个回答
字典没有大小限制
d = {}
for i in xrange(999999):
d[i] = i
len(d)
它会打印
999999
你在构造字符串时,i
和j
之间没有分隔符,这样像(12, 1, 0)
和(1, 21, 0)
这样的元组会产生相同的名字。如果可以的话,干脆不要给这些东西起名字,直接用数字就行了:
var_dict[i, j, k] = f(i, j, k, other_params)
如果f
确实需要一个字符串,那就改一下名字的构造方式,在i
和j
之间加个分隔符:
var_name = 'x_{}_{}_{}'.format(i, j, k)
如果可能的话,即使f
需要一个字符串,也可以把元组当作字典的键来用:
var_dict[i, j, k] = f(var_name, other_params)
在Python字典中,用字符串作为键来访问数据的时间大约是1微秒(1秒除以1000再除以1000)。
这个时间会随着字典中条目数量的增加而稍微变长,可能是以一种类似于对数的方式增加,也就是说,条目越多,时间增加的幅度会变得越来越小。
但是,当字典的大小超过2的26次方(67,108,864)时,性能会明显下降。比如,读取一个大小为2的27次方(134,217,728)的字典,所需时间会变成原来的30倍,而对于一个大小为2的28次方(268,435,456)的字典,时间会变成原来的9000倍。我的电脑在达到2的29次方时就已经内存不够用了。
所以,关于Python中字典的最大大小,实际的答案是:
2的26次方 = 67,108,864
>>> for i in range(1,sys.maxsize):
... key = str(i)
... d[key] = key
... if math.log2(i) % 1 == 0:
... time_start = time.perf_counter()
... value = d[key]
... time_taken = time.perf_counter() - time_start
... print(time_taken*1000*1000, i)
...
0.682000063534360 1
0.521999936609063 2
0.394000153391971 4
0.365999994755839 8
0.424000063503626 16
0.380000074073905 32
0.365000005331239 64
0.447000047643086 128
0.413999941883957 256
0.481999904877739 512
0.641000042378436 1024
0.906999957805965 2048
0.616000079389778 4096
0.995999926090007 8192
1.115000031859381 16384
1.142999963121838 32768
1.144999941971036 65536
1.156000053015304 131072
1.231999931405880 262144
1.225999994858284 524288
1.196000084746629 1048576
1.308000037170131 2097152
1.232000158779556 4194304
1.314999963142327 8388608
1.178000047730165 16777216
1.179000037154764 33554432
1.669000084802974 67108864
33.22600014143973 134217728
9655.005000013261 268435456
Killed: 9
问题出在这里:
str(i)+str(j)
这样做不会生成唯一的标识符。举个例子,当 i=1
和 j=11
时设置的值,会被当 i=11
和 j=1
时设置的值覆盖(还有很多类似的情况)。
你可以通过在这两个数字之间插入一些分隔符(比如像你在 j
和 k
之间用的下划线)来解决这个问题。