词典是否在Python 3.6+;中排序;?

词典是否在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的顺序。)通过以下

字典是在Python3.6中排序的(至少在CPython实现下),这与以前的版本不同。这似乎是一个实质性的变化,但这只是文章中的一小段。它被描述为一个CPython实现细节,而不是一个语言特性,但也意味着这可能成为未来的标准

在保持元素顺序的同时,新的dictionary实现如何比旧的dictionary实现执行得更好

以下是文档中的文本:

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

让您的代码成为未来的证明:)

关于这一点有争论


编辑: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_条目
    获取相应的条目。由于只保留索引,因此此数组的类型取决于字典的总体大小(从类型(
    1
    byte)到
    32
    /
    64
    位构建上的/(
    4
    /
    8
    字节)

在以前的实现中,必须分配
PyDictKeyEntry
和size
dk_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']]