为什么 Python 在访问未设置的 属性 时抛出 KeyError?

Why does Python throw a KeyError when accessing an unset property?

在 Python 字典上访问未设置的 属性 时抛出 KeyError 而不是返回 None 的基本原理和含义是什么?

我知道语言设计涉及权衡,其中一些基于实际问题,一些主要基于哲学。从计算机科学的角度来看,为什么 Python 是这样设计的?

提出问题的几个注释

首先,让我们回顾一下我们的术语:

...when accessing an unset property on a Python dictionary

您没有访问 属性。您正在检索密钥。这就是为什么它被称为 KeyError。属性是属性的特例,这就是为什么它们会引发 AttributeError 而不是

至于为什么,还要感谢类型论。我有一本字典 d,其中(比如说)字符串作为键,整数作为值。对于 any k,这条规则确实应该成立:

assert isinstance(d[k], int)

如果您 return None,那么在这种情况下规则将失败。引发异常是表明您无法满足操作的后置条件的正常方式。在这种情况下,断言没有机会触发,因为在表达式仍在计算时引发了异常。

来自Python design philosophy:

  • Errors should not be fatal. That is, user code should be able to recover from error conditions as long as the virtual machine is still functional.
  • At the same time, errors should not pass silently (These last two items naturally led to the decision to use exceptions throughout the implementation.)

还有一个经典案例,不喜欢大喊大叫的语言被破坏了:None并不总是意味着缺少密钥(这意味着消息被破坏),它也可能意味着可选的,但未设置密钥(没关系)。以JSON:

为例
>>> j = json.loads('{ "key": null }')
>>> j['key']
>>> j['nokey']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'nokey'

使用 None-默认情况下,此示例变得更加笨拙。以 PHP 为例:

json_decode returns null for invalid input, even though null is also a perfectly valid object for JSON to decode to—this function is completely unreliable unless you also call json_last_error every time you use it.

来自PHP: a fractal of bad design

一个dict可以存储任何值(包括None)所以唯一的方法(当使用[]语法时)来区分在丢失的密钥和映射到您认为的任何内容的密钥之间 将是一个很好的哨兵是提出一个例外。

>>> d = {'foo': None}
>>> print d['foo']
None
>>> print d['bar']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'bar'

对于您不关心区别的情况,您可以改用 get 方法,它故意 returns None(或您选择的标记)用于不存在的键。

>>> print d.get('bar')
None
>>> print d.get('bar', 7)
7