python - 当字典键相同时,为什么 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 上运行了上面的代码。)
解决方案
如果你的问题是为什么 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 源构建文档。
推荐阅读
- r - 如何在 ggplot2 中为绘图的所有部分使用 Sherman Serif 字体(例如,标题、x.axis、y.axis)
- typescript - 如何定义接受接口/类型具有特定属性的泛型类型?
- node.js - 上传文件时出现“错误:MultipartParser.end():流意外结束”错误
- python - Spyder 不允许我使用 PyQt-5.15,有没有办法可以使用 PyQt-5.15 功能?
- php - Laravel 8,User = null,但会话仍有“_token”,会话持久性问题?
- python - 如何使用 Haar Cascade 获得人脸检测的置信度值
- node.js - 如何从 Mongoose 中创建 observable
- html - 如何以角度创建列卡?
- python - 防止在字符串python中的某些地方格式化
- go - 为什么 writer.Write(msg) 无法写入 os.Stdout?