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() 保证啥顺序? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Python:字典

字典排序

python 字典操作

python易混易乱

python基础

Python 3.0 - dict 方法返回视图 - 为啥?