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?

### 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 `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.
* 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](http://www.cs.virginia.edu/~weimer/p/weimer-toplas2008.pdf)
* If Python returned `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?