我试图了解python 3.6.7
和python 3.5.2
中python字典之间的区别。他们存储键值对顺序的方式似乎有所不同。
例如,假设有一个名为di
的字典:
di = {'a':1,'A':1,'b':2, 'B':2, 'c':3, 'C':3}
在Python 3.5.2
中,当我打印di
时,输出为:
{'C': 3, 'a': 1, 'A': 1, 'B': 2, 'c': 3, 'b': 2}
但是,在Python 3.6.7
中是:
{'a': 1, 'A': 1, 'b': 2, 'B': 2, 'c': 3, 'C': 3}
两个版本之间有哪些更改?
如何使我的代码对python 3.6.7
的结果进行排序,使其类似于3.5.2
的结果。
P.S。我知道Python字典中实际上没有无订单。这里的术语order
用于使读者易于理解我的问题。
谢谢。
答案 0 :(得分:3)
“允许”字典的顺序对于程序的每次运行都不同,更不用说版本了。在每个版本上始终按顺序订购只有CPython知道的实现细节 *的事实。您的程序不应依赖此行为。
如何使我的代码对python 3.6.7的结果进行排序(类似于3.5.2的结果)。
使用OrderedDict!
*实际上,as of Python 3.7中,保留插入顺序正式是语言规范的一部分。
答案 1 :(得分:3)
TLDR:
要复制基于散列的排序,必须采用显式排序的dict
并强加自己的排序。
from collections import OrderedDict
def cpy35dict(source_dict):
"""Apply hash-ordering to a dictionary"""
return OrderedDict( # ensure stable ordering
sorted( # order items by key hash
source_dict.items(),
key=lambda item: hash(item[0])
)
)
这将复制CPython直至Python 3.5中使用的顺序。 请注意,Python语言规范对Python 3.7之前的订单不提供 no 保证-如果您坚持订购,则还应在Python 3.5和更早版本中使用此保证。
dict
类容器基本上有三种类型的订单:
根据Python规范,dict
具有任意顺序(最高至Python 3.6)和插入顺序(自Python 3.7起)。
在3.7版中进行了更改:保证字典顺序为插入顺序。此行为是3.6版CPython的实现细节。 [Mapping Types — dict¶]
但是,任意顺序并不排除特定顺序。它的基本含义是“无论实现感觉如何”。不同的实现使用不同的方案来实现dict
。
PyPy自Python 2.7/3.2
CPython 3.5-使用基础哈希函数的顺序。由于几种类型都有加盐的哈希,这意味着您每次调用都会获得不同的顺序。
CPython 3.6使用插入项目的顺序。这显然是实现细节。
此新实现的顺序保留方面被认为是实现细节,不应依赖于[What's new in Python 3.6]
换句话说,Python 3.6和更早版本的代码应该对dict
的顺序做出 no 假设。仅适用于Python 3.7和更高版本的代码应假设dict
的顺序。