更新:
在Python 3.6中,
dict
有一个
new implementation
这保持了插入顺序。在Python 3.7中,这种保序行为是
guaranteed
:
插入顺序的保存性质
dict
物体
has been declared
成为Python语言规范的官方部分。
这是一个
security fix
从2012年开始
enabled by default
在Python 3.3中(向下滚动到“安全性改进”)。
根据公告:
哈希随机化导致dicts和set的迭代顺序为
不可预测,并且在Python运行中有所不同。Python从未保证
dict或集合中键的迭代顺序,建议应用程序永远不要
依赖它。从历史上看,dict迭代顺序在
释放,并且在连续执行
蟒蛇因此,一些现有的应用程序可能依赖于dict或集合排序。
正因为如此,而且许多Python应用程序不接受
在所有稳定的Python版本中,不受信任的输入都不易受到此攻击
这里提到,HASH随机化是默认禁用的。
如上所述,最后一个大写位在Python 3.3中不再为真。
另请参阅:
object.__hash__()
documentation
(“注意”侧边栏)。
如果绝对必要,可以通过设置
PYTHONHASHSEED
环境变量到
0
.
你的反例:
list({str(i): i for i in range(10)}.keys())
做
不
事实上,在Python 3.3中总是给出相同的结果,尽管不同排序的数量是有限的
due to
处理哈希冲突的方式:
$ 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']