Update:在Python 3.6中,dict
has a 新的实施 https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-compactdict它保留插入顺序。从 Python 3.7 开始,这种保序行为是保证 https://docs.python.org/3/whatsnew/3.7.html:
插入顺序保存性质dict https://docs.python.org/3/library/stdtypes.html#typesmapping物体已宣布 https://mail.python.org/pipermail/python-dev/2017-December/151283.html成为 Python 语言规范的正式部分。
这是一个结果安全修复 http://mail.python.org/pipermail/python-announce-list/2012-March/009394.html从 2012 年开始,即默认启用 http://docs.python.org/3/whatsnew/3.3.html在 Python 3.3 中(向下滚动到“安全改进”)。
从公告来看:
哈希随机化导致字典和集合的迭代顺序为
不可预测,并且在不同的 Python 运行中有所不同。 Python从来不保证
字典或集合中键的迭代顺序,建议应用程序永远不要
依靠它。从历史上看,字典迭代顺序并没有经常改变
发布并在连续执行之间始终保持一致
Python。因此,一些现有的应用程序可能依赖于字典或集合排序。
因此,许多 Python 应用程序不接受
在所有稳定的 Python 版本中,不受信任的输入不易受到此攻击
这里提到,哈希随机化默认是禁用的。
如上所述,最后一个大写位在 Python 3.3 中不再适用。
也可以看看: object.__hash__()文档 http://docs.python.org/3/reference/datamodel.html#object.__hash__(“注意”侧边栏)。
如果绝对必要,您可以在受此行为影响的 Python 版本中禁用哈希随机化,方法是设置PYTHONHASHSEED https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED环境变量为0
.
你的反例:
list({str(i): i for i in range(10)}.keys())
… does not事实上,在 Python 3.3 中总是给出相同的结果,尽管不同排序的数量是有限的due to https://stackoverflow.com/q/26136894/1014938处理哈希冲突的方式:
$ for x in {0..999}
> do
> python3.3 -c "print(list({str(i): i for i in range(10)}.keys()))"
> done | sort | uniq -c
61 ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
73 ['1', '0', '3', '2', '5', '4', '7', '6', '9', '8']
62 ['2', '3', '0', '1', '6', '7', '4', '5', '8', '9']
59 ['3', '2', '1', '0', '7', '6', '5', '4', '9', '8']
58 ['4', '5', '6', '7', '0', '1', '2', '3', '8', '9']
55 ['5', '4', '7', '6', '1', '0', '3', '2', '9', '8']
62 ['6', '7', '4', '5', '2', '3', '0', '1', '8', '9']
63 ['7', '6', '5', '4', '3', '2', '1', '0', '9', '8']
60 ['8', '9', '0', '1', '2', '3', '4', '5', '6', '7']
66 ['8', '9', '2', '3', '0', '1', '6', '7', '4', '5']
65 ['8', '9', '4', '5', '6', '7', '0', '1', '2', '3']
53 ['8', '9', '6', '7', '4', '5', '2', '3', '0', '1']
62 ['9', '8', '1', '0', '3', '2', '5', '4', '7', '6']
52 ['9', '8', '3', '2', '1', '0', '7', '6', '5', '4']
73 ['9', '8', '5', '4', '7', '6', '1', '0', '3', '2']
76 ['9', '8', '7', '6', '5', '4', '3', '2', '1', '0']
正如本答案开头所述,Python 3.6 中不再是这种情况:
$ for x in {0..999}
> do
> python3.6 -c "print(list({str(i): i for i in range(10)}.keys()))"
> done | sort | uniq -c
1000 ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']