There comes a time in every programmer’s life where she feels like a program or language is “out to get her”. This is what I eventually came to recognize as a gotcha, or “a feature of a system, a program or a programming language that works in the way it is documented but is counter-intuitive and almost invites mistakes”.
I was recently gotten by a Python convenience function,
dict.get(key[, default]), which you might use if you’re working with dictionaries. Let’s make sure it doesn’t get you, too!
Python has a useful data structure, the dictionary, which is “best [thought of] as an unordered set of key:value pairs”. The cool thing about dictionaries is that they associate almost any one thing to another (whereas a list only associated an index with a value – see Learn Python the Hard Way). With a dictionary, you can store a value with a key, extract a value with a key, or delete a value with a key.
Let’s store a few values to a few keys.
You can add values
and get them with the same subscript syntax.
What happens when we try to get the value for a key that doesn’t exist?
There are some cases where, instead of a
KeyError, we have a default value for keys that are missing from a dictionary. That’s where
get comes in handy.
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 Python Standard Library
Let’s say we have a dictionary to keep track of animal sightings. This dictionary has animal names as keys and an integer value for number of sightings.
We want to check whether there have been sightings of the fabled Front-Facing Baby Chick (🐥) lately, but we’re not sure that it’s been stored in the dictionary as a key. We also know that if
Front-Facing Baby Chick isn’t a key in the dictionary, we should assume that it has been sighted
This is where we use
Awesome! Now we can get a default value from a key instead of a
KeyError. This is also much more readable than:
Here’s Where They Get You
Your Pythonista friend, Alice, thought she saw a Front-Facing Baby Chick (🐥) but then realized it was a run of the mill Baby Chick (🐤), and she thought that her mistake probably invalidated everyone else’s sightings, too.2 This is how she chose to record it.
What do you think happens now?
get tries to find the value associated with
Front-Facing Baby Chick, and since the value is
None, it uses the default value passed in as a parameter,
Under the covers, the implementation of
get might look something like this:
Which makes sense. If you call
dict.get("Front-Facing Baby Chick", False), we don’t get a
KeyError – we get
None, which was a value in the dictionary. Getting a value
None associated with a key is different from the key not being in the dictionary, and
get does exactly what the docs say: “return the value for key if key is in the dictionary”.
So next time you try to specify a default, non-
None value for a key that might be in a dictionary, remember that getting
None back will still be possible.
Don’t let them get you 🐥.
Is there ever a reason to set a key’s value to
None in a dictionary?
What are your favorite gotchas to watch out for?
X = None ↩
While Alice decided that her mistake invalidated
Front-Facing Baby Chicksightings, she didn’t then attribute the sightings of
Front-Facing Baby Chickto sightings of the regular
Baby Chick. She just chose to set one key to
None. This is mainly a thought exercise, and hopefully you will not encounter Pythonista friends who set keys to
Instead of storing a value,
None, to a key, Alice probably should have decremented the value by 1 or deleted the key. ↩