31

Why does this throw a KeyError:

d = dict()
d['xyz']

But this does not?

d = dict()
d.get('xyz')

I'm also curious if descriptors play a role here.

foundling
  • 1,695
  • 1
  • 16
  • 22
  • 4
    That's basically the entire practical difference between the two ways - it's there so that you can handle `None` (or a specified default) or exceptions at your discretion. Are you curious about the implementation details? – TigerhawkT3 May 21 '15 at 02:31
  • Thanks, yes, I am curious about the lower-level details, specifically how a KeyError is avoided with the 'if k in d' construct. And is it a KeyError with d['xyz'] (if 'xyz' doesn't exist) because this is 'raw' or direct access to a dict object? It seems like the answer to my question as i've stated it is 'because this is how it works', so maybe I'm making too much of what are ultimately design decision, i.e. when to raise a fuss and when not to. – foundling May 21 '15 at 03:18
  • The lower level details aren't hard to imagine; you could write the equivalent method yourself by just returning the second argument passed in on keyError. – Kyle Baker Jun 07 '16 at 20:40

4 Answers4

31

This is simply how the get() method is defined.

From the Python docs:

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

The default "not-found" return value is None. You can return any other default value.

d = dict()
d.get('xyz', 42)  # returns 42
Martin Konecny
  • 57,827
  • 19
  • 139
  • 159
5

Accessing by brackets does not have a default but the get method does and the default is None. From the docs for get (via a = dict(); help(a.get))

Help on built-in function get:

get(...)
    D.get(k[,d]) -> D[k] if k in D, else d.  d defaults to None.
foundling
  • 1,695
  • 1
  • 16
  • 22
Eric Renouf
  • 13,950
  • 3
  • 45
  • 67
3

Simply because [ 1 ] the key is not in the map and [ 2 ] those two operations are different in nature.

From dict Mapping Types:

d[key]

Return the item of d with key key. Raises a KeyError if key is not in the map.

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

tjeloep
  • 318
  • 1
  • 4
  • 19
1

Your opening question is well answered, I believe, but I don't see any response to

I'm also curious if descriptors play a role here.

Technically, descriptors do play a role here, since all methods are implemented implicitly with a descriptor, but there are no clear explicit descriptors being used, and they have nothing to do with the behavior you're questioning.

Jacob Zimmerman
  • 1,521
  • 11
  • 20