<hr/>
<p><strong>更新:</strong>在Python 3.6中,<code>dict</code>有一个保持插入顺序的<a href="https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-compactdict" rel="noreferrer">new implementation</a>。在Python 3.7中,这种保序行为是<a href="https://docs.python.org/3/whatsnew/3.7.html" rel="noreferrer">guaranteed</a>:</p>
<blockquote>
<p>the insertion-order preservation nature of <a href="https://docs.python.org/3/library/stdtypes.html#typesmapping" rel="noreferrer">dict</a> objects <a href="https://mail.python.org/pipermail/python-dev/2017-December/151283.html" rel="noreferrer">has been declared</a> to be an official part of the Python language spec.</p>
</blockquote>
<hr/>
<p>这是2012年的<a href="http://mail.python.org/pipermail/python-announce-list/2012-March/009394.html" rel="noreferrer">security fix</a>结果,在Python 3.3中是<a href="http://docs.python.org/3/whatsnew/3.3.html" rel="noreferrer">enabled by default</a>(向下滚动到“安全改进”)。</p>
<p>从公告中:</p>
<blockquote>
<p>Hash randomization causes the iteration order of dicts and sets to be
unpredictable and differ across Python runs. Python has never guaranteed
iteration order of keys in a dict or set, and applications are advised to never
rely on it. Historically, dict iteration order has not changed very often across
releases and has always remained consistent between successive executions of
Python. Thus, some existing applications may be relying on dict or set ordering.
Because of this and the fact that many Python applications which don't accept
untrusted input are not vulnerable to this attack, in all stable Python releases
mentioned here, HASH RANDOMIZATION IS DISABLED BY DEFAULT.</p>
</blockquote>
<p>如上所述,最后一个大写的位在Python3.3中不再正确。</p>
<p><strong>另请参见:</strong><a href="http://docs.python.org/3/reference/datamodel.html#object.__hash__" rel="noreferrer">^{<cd2>} documentation</a>(“注意”侧边栏)。</p>
<p>如果绝对必要,可以通过将<a href="https://docs.python.org/3/using/cmdline.html#envvar-PYTHONHASHSEED" rel="noreferrer">^{<cd3>}</a>环境变量设置为<code>0</code>,在受此行为影响的Python版本中禁用散列随机化。</p>
<hr/>
<p>你的反例:</p>
<pre><code>list({str(i): i for i in range(10)}.keys())
</code></pre>
<p>…在Python 3.3中,<em>不</em>实际上总是给出相同的结果,尽管不同顺序的数量是有限的<a href="https://stackoverflow.com/q/26136894/1014938">due to</a>处理散列冲突的方式:</p>
<pre><code>$ 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']
</code></pre>
<p>如本答案开头所述,Python3.6不再是这样:</p>
<pre><code>$ 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']
</code></pre>