首页 > 解决方案 > 当字典键相同时,为什么 Python 只保留最后一个键值对?

问题描述

假设我创建了一个字典a_dictionary,其中两个键值对具有相同的键:

In [1]: a_dictionary = {'key': 5, 'another_key': 10, 'key': 50} 

In [2]: a_dictionary
Out[2]: {'key': 50, 'another_key': 10}

为什么 Python 在这里选择保留最后一个键值对,而不是抛出关于使用相同键的错误(或至少引发警告)?

在我看来,这里的主要缺点是您可能会在不知情的情况下丢失数据。

(如果相关,我在 Python 3.6.4 上运行了上面的代码。)

标签: pythonpython-3.xdictionary

解决方案


如果你的问题是为什么 Python dict 显示最初是这样设计的……可能没人知道。


我们知道何时做出决定。Python 0.9.x (1991-1993) 没有 dict 显示;Python 1.0.x (1994) 做到了。他们的工作方式与今天完全相同。来自文档:1

字典显示产生一个新的字典对象。

键/数据对从左到右评估以定义字典的条目:每个键对象用作字典中的键以存储相应的数据。

前面部分类型中列出了对键值类型的限制。

未检测到重复键之间的冲突;为给定键值存储的最后一个数据(显示中最右边的文本)优先。

并且,测试它:

$ ./python
Python 1.0.1 (Aug 21 2018)
Copyright 1991-1994 Stichting Mathematisch Centrum, Amsterdam
>>> {'key': 1, 'other': 2, 'key': 3}
{'other': 2, 'key': 3}

但是没有提到为什么 Guido 选择了这种设计:

此外,如果您查看具有相似功能的不同语言,其中一些保留最后一个键值对,如 Python,一些保留任意键值对,一些引发某种错误......不要争辩说这是一个显而易见的设计,这就是 Guido 选择它的原因。


如果你想要一个可能并不比你自己猜测的更好的猜测,这里是我的:

编译器不仅可以而且确实可以通过创建一个空的 dict 并将键值对插入其中来有效地从文字中构造 const 值。因此,默认情况下,您会获得允许重复、最后一个键获胜的语义;如果您想要其他任何东西,则必须编写额外的代码。而且,没有令人信服的理由来选择一个而不是另一个,Guido 选择不编写额外的代码。


那么,如果这个设计没有令人信服的理由为什么从那以后的 24 年里没有人试图改变它呢?

好吧,有人提出了功能请求(bpo #16385),以使重复键在 3.4 中成为错误。但显然在有人建议它启动时消失了-ideas。)它可能已经出现了几次,但显然没有人希望它改变得足以推动它。

同时,他最接近 Python 现有行为的实际论点是 Terry J. Reedy 的评论:

如果没有更多用例和支持(来自关于 python-ideas 的讨论),我认为这应该被拒绝。能够重写键是 Python 字典的基础,以及为什么它们可以用于 Python 的可变命名空间。一次写入或一次写入键的字典将是另一回事。

至于文字,代码生成器可能依赖于能够编写重复的键,而不必返回并删除以前的输出。


1. 我不认为 1.0 的文档可以直接链接到任何地方,但是您可以下载整个 1.0.1 源存档并从 TeX 源构建文档。


推荐阅读