What are the rationale and implications for throwing KeyError
instead of returning None
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?
None
), or if the choice was philosophical (i.e., "accessing an unset property is, in Guido's opinion, an exceptional case").dict.get
function has this functionality, but the literal notation appears to be optimizing for the case where the program considers an unset value exceptional.None
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?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: None
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:
>>> j = json.loads('{ "key": null }')
>>> j['key']
>>> j['nokey']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 'nokey'
With None
-by-default this example becames more clunky. Take, PHP, for example:
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 calljson_last_error
every time you use it.