词典是否在Python 3.6+;中排序;?
字典是在Python3.6中排序的(至少在CPython实现下),这与以前的版本不同。这似乎是一个实质性的变化,但这只是文章中的一小段。它被描述为一个CPython实现细节,而不是一个语言特性,但也意味着这可能成为未来的标准 在保持元素顺序的同时,新的dictionary实现如何比旧的dictionary实现执行得更好 以下是文档中的文本:词典是否在Python 3.6+;中排序;?,python,python-3.x,dictionary,python-internals,python-3.6,Python,Python 3.x,Dictionary,Python Internals,Python 3.6,字典是在Python3.6中排序的(至少在CPython实现下),这与以前的版本不同。这似乎是一个实质性的变化,但这只是文章中的一小段。它被描述为一个CPython实现细节,而不是一个语言特性,但也意味着这可能成为未来的标准 在保持元素顺序的同时,新的dictionary实现如何比旧的dictionary实现执行得更好 以下是文档中的文本: dict()现在使用“紧凑”表示。与Python 3.5相比,新dict()的内存使用量减少了20%到25%。(保留函数中**kwargs的顺序。)通过以下
dict()
现在使用“紧凑”表示。与Python 3.5相比,新dict()的内存使用量减少了20%到25%。(保留函数中**kwargs的顺序。)通过以下方式实现。这个新实现的顺序保持方面被认为是一个实现细节,不应该依赖它(这在将来可能会发生变化,但在将语言规范更改为所有当前和未来Python实现的命令保留语义之前,希望在一些版本中使用这种新的dict实现;这也有助于保持与旧版本的语言的向后兼容性,其中随机迭代离子顺序仍然有效,例如Python 3.5)。(INADA Naoki在.Idea中提供。)
2017年12月更新:
dict
s保留插入顺序适用于Python 3.7下面回答了最初的第一个问题:
我应该在Python 3.6中使用dict
还是orderedict
我认为文档中的这句话实际上足以回答您的问题
这个新实现的顺序保持方面被认为是一个实现细节,不应该依赖它
dict
并不是一个明确的有序集合,因此如果您想保持一致性,不依赖新实现的副作用,您应该坚持使用orderedict
让您的代码成为未来的证明:)
关于这一点有争论
编辑:Python3.7将保留此功能
词典是否在Python 3.6+中排序?
它们是按插入顺序排列的。从Python3.6开始,对于Python的CPython实现,字典会记住插入项的顺序。这被认为是Python 3.6中的一个实现细节;如果希望在其他Python实现中保证插入顺序(以及其他有序行为),则需要使用OrderedDict
从Python 3.7开始,这不再是一个实现细节,而是一个语言特性:
就这样吧。“Dict保持插入顺序”是裁决。谢谢
这仅仅意味着你可以依赖它。如果Python的其他实现希望成为符合Python3.7标准的实现,那么它们还必须提供插入顺序字典
Python
3.6
字典实现在保持元素顺序的同时,如何比旧的实现性能更好[2]
本质上,通过保留两个数组
- 第一个数组按插入顺序保存字典的条目()。保持顺序是通过这样一个仅附加的数组来实现的,其中新项总是在末尾插入(插入顺序)
- 第二,保存
数组的索引(即,指示相应条目在dk_条目
中的位置的值)。此数组充当哈希表。当一个键被散列时,它会导致存储在dk_条目
中的一个索引,并通过索引dk_index
获取相应的条目。由于只保留索引,因此此数组的类型取决于字典的总体大小(从类型(dk_条目
byte)到1
/32
位构建上的/(64
/4
字节)8
PyDictKeyEntry
和sizedk_size
类型的稀疏数组;不幸的是,由于该数组不允许超过2/3*dk_size
full,因此它还导致了大量的空白。(空的空间仍然有PyDictKeyEntry
size!)
现在情况并非如此,因为只存储了所需的条目(已插入的条目),并且保留了类型为intX\u t
(X
取决于dict大小)的稀疏数组2/3*dk\u size
s full。空格从类型PyDictKeyEntry
更改为intX\u t
因此,显然,创建PyDictKeyEntry
类型的稀疏数组比存储int
s的稀疏数组需要更多的内存
如果您感兴趣,可以查看有关此功能的完整对话,这是一本很好的读物
,可以看到所用数据结构的可视化,它抓住了想法的要点 例如,字典:
d = {'timmy': 'red', 'barry': 'green', 'guido': 'blue'}
当前存储为[keyhash,key,value]:
entries = [['--', '--', '--'],
[-8522787127447073495, 'barry', 'green'],
['--', '--', '--'],
['--', '--', '--'],
['--', '--', '--'],
[-9092791511155847987, 'timmy', 'red'],
['--', '--', '--'],
[-6480567542315338377, 'guido', 'blue']]
相反,数据应按如下方式组织:
indices = [None, 1, None, None, None, 0, None, 2]
entries = [[-9092791511155847987, 'timmy', 'red'],
[-8522787127447073495, 'barry', 'green'],
[-6480567542315338377, 'guido', 'blue']]
正如您现在可以直观地看到的,在最初的方案中,大量空间基本上是空的,以减少碰撞并加快查找速度。使用新方法,您可以通过在索引中将稀疏性移动到真正需要的位置来减少所需的内存
[1] :我说“插入有序”而不是“有序”,因为存在OrderedDict,“有序”表示进一步的行为,`dict`对象*不提供*。OrderedDicts是可逆的,提供顺序敏感的方法,主要是提供顺序敏感的相等性测试(`=`,`!=`)`dict's目前不提供任何此类行为/方法。
[2] :新字典实现的性能更好