Python dictionary default values

Python Dictionary Default Values. Python dictionaries have a get() method that provides alternative values when looking up a key. This method is suitable for many situations. The following is a simple example to demonstrate. Suppose we have the following data structure that maps user IDs to usernames:

name_for_userid = {
382: 'Alice',
950: 'Bob',
590: 'Dilbert',
}

We now want to use this data structure to write a greeting() function that returns a greeting to the user given their user ID. A first implementation might look like this:

def greeting(userid):
return 'Hi %s!' % name_for_userid[userid]

This performs a straightforward dictionary lookup. However, this implementation only works correctly if the user ID is in the name_for_userid dictionary. If an invalid user ID is passed to the greeting function, an exception will be thrown:

>>> greeting(382)
'Hi Alice!'

>>> greeting(33333333)
KeyError: 33333333

We don’t want to see a KeyError exception, so it’s best to have the function return a generic greeting as a fallback if the user ID is not found.
Let’s implement this idea. The first thing that comes to mind might be to look up the key in the dictionary and return a default greeting if the userid is not found:

def greeting(userid):
if userid in name_for_userid:
return 'Hi %s!' % name_for_userid[userid]
else:
return 'Hi there!'

Using the previous test case for this greeting() implementation:

>>> greeting(382)
'Hi Alice!'

>>> greeting(3333333)
'Hi there!'

That’s much better, unknown users now get a generic greeting, and when a valid userid is found, they get a personalized greeting.
While this new implementation does what you expect and looks short and concise, it can still be improved. The current approach has several drawbacks.

  • It’s inefficient, requiring two dictionary queries.
  • It’s verbose, and the greeting string is somewhat repetitive.

  • It’s not very Pythonic. The official Python documentation specifically recommends using the “easier to ask for forgiveness than permission” (EAFP) coding style:

This common Python coding style assumes the existence of valid keys or attributes, and then catches exceptions if this assumption is incorrect.

A better implementation based on EAFP principles doesn’t explicitly check if the key is included, but instead uses a try...except block to catch KeyError:

def greeting(userid):
try:
return 'Hi %s!' % name_for_userid[userid]
except KeyError:
return 'Hi there'

This implementation also meets the original requirements and avoids querying the dictionary twice.
However, it can be further improved to become a more concise solution. Python dictionaries have a get() method that can be passed a “default” argument to use as a fallback value:

def greeting(userid):
return 'Hi %s!' %
name_for_userid.get( userid, 'there')

When get() is called, it checks whether the given key exists in the dictionary. If so, it returns the value for that key. If not, it returns the default fallback value. As you can see above, this implementation of greeting still works as expected:

>>> greeting(950)
'Hi Bob!'

>>> greeting(333333)
'Hi there!'

The final implementation of greeting() is clean and concise, using only features from the Python standard library. Therefore, I think it is the best solution for this particular case.

Key Takeaways

  • Avoid explicitly checking dictionary keys when testing for containment.

  • Use EAFP-style exception handling or use the built-in get() method instead.

  • In some cases, the collections.defaultdict class from the standard library can be used.

Leave a Reply

Your email address will not be published. Required fields are marked *