Update:在Python 3.6中,dict
有一个保留插入顺序的new implementation.在Python 3.7中,这种保序行为是guaranteed:
dict个对象has been declared的插入顺序保留性质将成为Python语言规范的正式部分.
这是2012年的security fix分的结果,在Python 3.3中是enabled by default分(向下滚动到"安全改进").
从公告中:
散列随机化导致dict和set的迭代顺序为
如上所述,最后一个大写的位在Python 3.3中不再正确.
See also: object.__hash__()
documentation("注意"侧栏).
如果绝对必要,可以通过将PYTHONHASHSEED
环境变量设置为0
,在受此行为影响的Python版本中禁用哈希随机化.
你的反例是:
list({str(i): i for i in range(10)}.keys())
…在Python 3.3中,not实际上总是给出相同的结果,尽管不同排序的数量受到哈希冲突处理方式的限制:
$ 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']