2

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

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

一些注释来构建问题

  • 我主要想知道这是否是一个实际的决定(即,它为开发人员提供了从错误中恢复的更多选择,而不仅仅是返回None),或者选择是否是哲学的(即,“访问未设置的属性是,在 Guido 的意见,一个例外情况”)。
  • Python 的dict.get函数具有此功能,但文字符号似乎正在针对程序认为未设置值异常的情况进行优化。
  • 值得注意的是,一些人认为异常处理很难推理,因为它涉及与主程序不同的控制流
  • 如果 Python 返回None而不是引发异常,程序仍然可以在访问它的值之前检查键的存在,如果它确实想要以不同的方式处理 unset 和None值。但由于我们无法访问异常编程流程,我有兴趣了解我们可能会失去什么?
4

3 回答 3

4

它来自Python 设计理念

  • 错误不应该是致命的。也就是说,只要虚拟机仍然正常工作,用户代码就应该能够从错误条件中恢复。
  • 同时,错误不应该无声无息地传递(最后两项自然导致决定在整个实现过程中使用异常。)

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

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

使用None-by-default 这个例子变得更加笨拙。以 PHP 为例:

json_decode为无效输入返回 null,即使 null 也是 JSON 解码到的完全有效的对象——这个函数是完全不可靠的,除非你json_last_error每次使用它时都调用它。

来自PHP:糟糕设计的分形

于 2015-05-12T23:41:18.357 回答
1

Adict可以存储任何值(包括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方法,该方法会故意返回None(或您选择的哨兵)不存在的键。

>>> print d.get('bar')
None
>>> print d.get('bar', 7)
7
于 2015-05-12T23:49:09.143 回答
0

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

...访问 Python 字典上未设置的属性时

您没有访问属性。您正在检索密钥。这就是为什么它被称为KeyError. 属性是属性的一种特殊情况,这就是为什么它们会AttributeError引发

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

assert isinstance(d[k], int)

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

于 2015-05-12T23:31:28.227 回答