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

时间:2015-05-12 23:26:01

标签: python exception-handling keyerror

What are the rationale and implications for throwing $configuration->setQuoteStrategy(new AnsiQuoteStrategy()); instead of returning KeyError when accessing an unset property on a Python dictionary?

I know that language design involves trade-offs, some of them based on practical concerns and some based primarily on philosophy. From a computer science perspective, why has Python been designed in this way?

A couple of notes to frame the question

  • I'm primarily curious to know if this was a practical decision (i.e., it gives the developer more options to recover from the error than just returning None), or if the choice was philosophical (i.e., "accessing an unset property is, in Guido's opinion, an exceptional case").
  • Python's None function has this functionality, but the literal notation appears to be optimizing for the case where the program considers an unset value exceptional.
  • It's worth noting that exception handling is considered by some to be hard to reason about because it involves a control flow that is distinct from the main program
  • If Python returned dict.get instead of raising an exception, a program could still check for the key's existence prior to accessing its value if it did want to treat unset and None values differently. But since we wouldn't have access to the exception programming flow, I'm interested to learn what we might lose?

3 个答案:

答案 0 :(得分:3)

It comes from 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.)

And there is a classic case, where language that do not prefer to yell are broke: leaks is not always means missing key (which means broken message), it may also mean optional, but unset key (which is OK). Take for example JSON:

None

With >>> j = json.loads('{ "key": null }') >>> j['key'] >>> j['nokey'] Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'nokey' -by-default this example becames more clunky. Take, PHP, for example:

None 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_decode every time you use it.

From PHP: a fractal of bad design

答案 1 :(得分:0)

First, let's review our terminology:

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

You are not accessing a property. You are retrieving a key. That's why it's called a fb://profile/10206768458598300. Properties are a special case of attributes, which is why they raise KeyError instead

As for the why, you have type theory to thank. I have a dictionary AttributeError with (say) strings as keys and integers as values. For any d, this rule really ought to hold:

k

If you return assert isinstance(d[k], int) , then the rule fails in that case. Raising an exception is the normal way of indicating that you can't satisfy an operation's postcondition. In this case, the assertion doesn't have a chance to fire, because the exception is raised while the expression is still being evaluated.

答案 2 :(得分:0)

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方法,故意返回None(或您选择的哨兵)以查找不存在的密钥

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