dict.keys() 和 dict.values() 保证啥顺序? [复制]
Posted
技术标签:
【中文标题】dict.keys() 和 dict.values() 保证啥顺序? [复制]【英文标题】:What ordering does dict.keys() and dict.values() guarantee? [duplicate]dict.keys() 和 dict.values() 保证什么顺序? [复制] 【发布时间】:2018-04-20 16:56:28 【问题描述】:这个问题来自this answer,其中一位用户 分别使用
d.keys()
和d.values()
来初始化一个数据帧。
众所周知,3.6以下的python版本中的字典是不排序的。
考虑以下形式的通用字典:
d = k1 : v1, k2 : v2, k3 : v3
其中键 k*
是任何可散列的对象,而值 v*
是任何对象。当然不能保证顺序,但是d.keys()
和d.values()
的顺序呢?
Python 2.x
d.keys()
和 d.values()
都返回列表。比如说,.keys()
按[k2, k1, k3]
的顺序返回d
的密钥。现在是否始终保证d.values()
返回与[v2, v1, v3]
相同的相对顺序?此外,无论这些函数被调用多少次,顺序是否保持不变?
Python 3.x (
我不是 100% 确定,但我相信 .keys
和 .values
在这里根本不保证任何排序,因为它们是类似集合的结构,因此根据定义没有顺序并且使您能够执行集合- 对它们进行类似操作。但我仍然想知道在这种情况下,两个调用之间是否存在 任何 种相对排序。 我猜不是。如果有人能肯定或纠正我,我将不胜感激。
【问题讨论】:
在 python 3.6+ 中(我认为)有命令,问题不是你是否可以使用它,而是你是否应该(我在“你应该”阵营)。另请参阅***.com/a/39980744/1240268 看起来keys()
和values()
出现的顺序相同。在 python 2 中,它是任意的(但一致) - 但在 python 3 中,它似乎是按定义顺序排列的。无论哪种方式,依赖这个都不是一个好主意......没有理由使用items()
。 Python 2 = repl.it/NwCu/0 Python 3 = repl.it/NwDC/0
@AndyHayden - 在我看来,规范中没有保证的事实是迄今为止不依赖它的最压倒性的理由:P 他们甚至在文档中说这是你应该的实现细节不要依赖...
@Shadow 我和Raymond Hettinger 在一起。我现在也到处使用 f-strings,所以如果他们想运行我的代码,每个人都必须升级。
@cᴏʟᴅsᴘᴇᴇᴅ 和 python 3 也是docs.python.org/3/library/stdtypes.html#dictionary-view-objects。也就是说,您链接到的答案没有损坏嗯,它仍然有点可疑 - 主要是因为您希望 .keys() 和 .values() 调用靠近在一起。如果有什么地方可以打赌它会达到我会的规格。
【参考方案1】:
一般规则:
-
在谈论什么是有保证的和什么不是保证之前,即使某些排序看起来是“有保证的”,但事实并非如此。你不应该依赖它。这被认为是不好的做法,可能会导致严重的错误。
d.keys()
、d.values()
和 d.items()
都以各自的顺序返回元素。该顺序应被视为任意顺序(不应对此作出任何假设)。 (docs)
对d.keys()
、d.values()
和d.items()
的连续调用是“稳定的”,因为它们可以保证保持先前调用的顺序(假设调用之间没有插入/删除)。李>
自 CPython 的 V3.6 以来,dict
has been reimplemented,它现在保留 插入 顺序。这不是更改的目标,而是副作用,它不是 python 规范的一部分,只是 CPython 实现的一个细节。请参阅上面的第 1 点:依赖这一点是不好的做法,不应该这样做。无论如何,您应该避免编写特定于 CPython 的代码。
在 Python2 中,顺序是确定性的(即,以相同的方式创建两次 dict 将产生相同的顺序)。在 Python
编辑:添加第 5 点,感谢@AndyHayden 的评论。
【讨论】:
谢谢,这再次证实了我的怀疑。你有什么可以借鉴的资源吗? 特别是第 3 部分)关于稳定排序是非常有用的信息,我不知道。因此,总而言之,无论是否存在相对排序,我都不应该假设存在。我说的对吗? 对于任何未来的读者,请参阅 CPython 实现脚注here,以及下面关于保证对应的位。 @AndyHayden 我没有参考资料,但是当您考虑它时,它是第 2 点的直接结果。如果调用keys()
然后values()
保留顺序,调用values()
然后keys()
保留顺序,则调用keys()
然后keys
() 保留顺序。对此给出正式证明很容易。
第 5 点中提到的非确定性是由于 Python 3 hash
函数的非确定性,该函数默认使用随机值来播种 str、bytes 和 datetime 的哈希值对象。您可以将 PYTHONHASHSEED 环境变量设置为(机器)整数以使其具有确定性。命令行帮助中简要提到了这一点,尽管该帮助声称您需要将 PYTHONHASHSEED 设置为“随机”以调用随机行为,但对于几个版本来说并非如此。以上是关于dict.keys() 和 dict.values() 保证啥顺序? [复制]的主要内容,如果未能解决你的问题,请参考以下文章