dict.keys()和dict.values()保证什么顺序?

cs9*_*s95 7 python dictionary python-2.x python-2.7

这个问题来自于这个答案,其中一个用户使用d.keys()d.values()单独初始化数据帧.

众所周知,3.6版本的python版本中的字典不是有序的.

考虑表单的通用字典:

d = {k1 : v1, k2 : v2, k3 : v3}
Run Code Online (Sandbox Code Playgroud)

其中键k*是任何可清洗对象,值v*是任何对象.当然,订单无法保证,但顺序d.keys()d.values()

Python 2.x

两者d.keys()d.values()返回列表.比如说,按顺序.keys()返回d[k2, k1, k3].难道现在总是保证d.values()返回相同的相对排序的[v2, v1, v3]?此外,无论调用这些函数多少次,顺序是否保持不变?

Python 3.x(<3.6)

我不是百分百肯定,但我相信.keys并且.values不保证这里有任何排序,因为它们是类似于集合的结构,因此没有按照定义的顺序,并且使您能够对它们执行类似集合的操作.但我仍然有兴趣知道在这个例子中两个调用之间是否存在任何相对排序.我猜不是.如果有人可以肯定或纠正我,我会很感激.

shx*_*hx2 9

一般规则:

  1. 在谈论保证什么和什么不保证之前,即使某些排序似乎是"保证",但事实并非如此.你不应该依赖它.它被认为是不好的做法,可能会导致令人讨厌的错误.
  2. d.keys(),d.values()d.items()所有元素按相应的顺序返回.该订单应视为任意(不应对其进行任何假设).(docs)
  3. 连续呼叫d.keys(),d.values()以及d.items()是"稳定",在这个意义上,这样可以保证维持以前的调用(假定没有插入/缺失的调用之间发生)的顺序.
  4. 由于CPython的V3.6 dict已经重新实现,现在它保留了插入顺序.这不是改变的目标,而是副作用,它不是python规范的一部分,只是CPython实现的一个细节.请参阅上面的第1点:依赖于此是不好的做法,不应该这样做.无论如何,你应该避免编写特定于CPython的代码.
  5. 在Python2中,顺序是确定性的(即以相同的方式创建一个dict两次将产生相同的顺序).在Python <3.6中,它不再是确定性的,所以你也不能依赖它(我不确定这个非确定性是规范的一部分还是仅仅是CPython实现细节).

编辑:加上第5点,感谢@ AndyHayden的评论.

  • 第5点中提到的非确定性是由于Python 3`hash`函数的非确定性,它默认使用随机值来为str,bytes和datetime对象的哈希值设定种子.您可以将PYTHONHASHSEED环境变量设置为(机器)整数,以使其具有确定性.在命令行帮助中简要提到了这一点,尽管该帮助声称您需要将PYTHONHASHSEED设置为"随机"以调用随机行为,但对于多个版本而言并非如此. (2认同)