使用哈希表的Python 3.6 字典实现
Python中的字典是数据值的集合,用于像地图一样存储数据值,与其他仅将单个值作为元素保存的数据类型不同,字典包含键:值对。字典中提供了键值,使其更加优化。字典中的每个键值对都用冒号分隔:,而每个键都用“逗号”分隔。要了解有关词典的更多信息,请单击此处。
根据 Raymond Hettinger 的提议,与Python v.3.5 或更低版本相比,新的 dict()函数的内存使用量减少了 20% 到 25%。它依赖于 Raymond Hettinger 提出的保序语义。此实现使字典更紧凑,并提供更快的迭代。
早期版本中字典的内存布局不必要地低效。它由一个 24 字节条目的稀疏表组成,其中存储了散列值、键指针和值指针。 3.5 及更低版本中字典的内存布局被实现为存储在单个稀疏表中。
例子:
for the below dictionary:
d = {'banana':'yellow', 'grapes':'green', 'apple':'red'}
used to store as:
entries = [['--', '--', '--'],
[-5850766811922200084, 'grapes', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[2247849978273412954, 'banana', 'yellow'],
['--', '--', '--'],
[-2069363430498323624, 'apple', 'red']]
相反,在新的 dict() 实现中,数据现在被组织在一个密集表中,该表由一个稀疏索引表引用,如下所示:
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[2247849978273412954, 'banana', 'yellow']
[-5850766811922200084, 'grapes', 'green'],
[-2069363430498323624, 'apple', 'red']]
重要的是要注意,在新的 dict() 实现中,只有数据布局发生了变化,哈希表算法没有变化。碰撞静力学和表搜索顺序都没有改变。
dict() 的这种新实现被认为可以根据 getdictionary 的大小显着压缩字典以节省内存。小型词典可以从中获得最大的好处。
对于具有 n 个条目的大小为 t 的稀疏表,大小为:
curr_size = 24 * t
new_size = 24 * n + sizeof(index) * t
在上面的示例香蕉/葡萄/苹果中,前一个实现的大小为 192 字节(八个 24 字节条目),后一个实现的大小为 90 字节(三个 24 字节条目和八个 1 字节索引)。这表明字典大小压缩了大约 58%。
除了节省内存,新的内存布局让迭代更快。现在,像 Keys()、items() 和 values 这样的函数可以在密集表上循环,而不必跳过空槽,这与旧的实现不同。这种新实现的其他好处是更好的缓存利用率、更快的大小调整和更少的内存接触。