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.
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.
 
    
    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
 
    
    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.
 
    
     
    
    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.
 
    
    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.
