为什么Python2.7中的字典比Python3中的字典占用更多的空间?

6
我已经阅读了Raymond Hettinger的新方法来实现紧凑字典。这解释了为什么Python 3.6中的字典比Python 2.7-3.5中的字典使用更少的内存。然而,在Python 2.7和3.3-3.5字典中似乎存在内存使用差异。测试代码:
import sys

d = {i: i for i in range(n)}
print(sys.getsizeof(d))
  • Python 2.7: 12568
  • Python 3.5: 6240
  • Python 3.6: 4704

如上所述,我了解3.5和3.6之间的差异,但我想知道2.7和3.5之间节省的原因。


嗯,我从没注意到这个,很好的发现。我不确定是否有所更改,以便普通字典可以从组合表格形式中受益(请参见我在实例字典上做的问答此处),但值得调查一下。虽然我怀疑 :-) - Dimitris Fasarakis Hilliard
1个回答

10

事实证明这是一个误导。在cPython 2.7-3.2和cPython 3.3之间以及cPython 3.4之后,增加字典大小的规则发生了变化(尽管此更改仅适用于删除时)。我们可以使用以下代码确定字典何时扩展:

import sys

size_old = 0
for n in range(512):
    d = {i: i for i in range(n)}
    size = sys.getsizeof(d)
    if size != size_old:
        print(n, size_old, size)
    size_old = size

Python 2.7:

(0, 0, 280)
(6, 280, 1048)
(22, 1048, 3352)
(86, 3352, 12568)

Python 3.5

0 0 288
6 288 480
12 480 864
22 864 1632
44 1632 3168
86 3168 6240

Python 3.6:

0 0 240
6 240 368
11 368 648
22 648 1184
43 1184 2280
86 2280 4704

记住字典在达到2/3容量时会自动调整大小,我们可以看到cPython 2.7字典实现在扩展时会增加4倍的大小,而cPython 3.5/3.6字典实现只会增加2倍的大小。

这在字典源代码中的注释中有解释:

/* GROWTH_RATE. Growth rate upon hitting maximum load.
 * Currently set to used*2 + capacity/2.
 * This means that dicts double in size when growing without deletions,
 * but have more head room when the number of deletions is on a par with the
 * number of insertions.
 * Raising this to used*4 doubles memory consumption depending on the size of
 * the dictionary, but results in half the number of resizes, less effort to
 * resize.
 * GROWTH_RATE was set to used*4 up to version 3.2.
 * GROWTH_RATE was set to used*2 in version 3.3.0
 */

1
如果Raymond Hettinger看到这个问题并告诉我们为什么他们做出了那个改变,那就太好了。 - PM 2Ring
1
@PM2Ring 我找到了“下一个最好的东西”(https://www.youtube.com/watch?v=p33CVV29OG8&feature=youtu.be&t=21m57s) - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接