A missing key often means none yet
A shop with no plums has 0 plums, so a missing key is not always a problem. Reading it with square brackets cannot say that. With stock = {"apples": 5}, the expression stock["plums"] stops the program with KeyError: 'plums'.
get with a default
d.get(key, default) takes a key and a default value. It gives the key's value when the key is in the dictionary and the default when it isn't. There is no error either way.
stock = {"apples": 5}
print(stock.get("apples", 0))
print(stock.get("plums", 0))
print(len(stock))
5
0
1
Reading with get does not add the key: stock still has one key afterwards. The default is only the answer to this one call.
The default is optional. Without it, get gives None for a missing key, so stock.get("plums") is None. That is useful when you want to tell "missing" apart from every real value, but for counts a default of 0 is usually what you want.
The same thing with an if
Before get, you would write the check by hand, using in:
plums = 0
if "plums" in stock:
plums = stock["plums"]
Four lines become one: plums = stock.get("plums", 0). The first form is still worth knowing, since it is the right shape when the missing case needs more than a default value, such as printing a message.
The lesson's task
The starter code already reads the pears with square brackets, because that key is there, and prints the first line. The new part is the plums: there are none in stock, so read "plums" with get and 0 as the default, store the answer in plums, and print it the same way as the pears line.
stock = {"apples": 5, "pears": 2}
pears = stock["pears"]
print(f"We have {pears} pears")
plums = stock.get("plums", 0)
print(f"We have {plums} plums")
We have 2 pears
We have 0 plums
The text inside f"..." is an f-string: the name in braces is replaced by its value when the line is printed.
Defaults that are not numbers
The default can be any value. ages.get("Ben", "unknown") gives the text unknown when Ben isn't in ages. A very common use is counting: read the old count with a default of 0, add 1, and store it back.
words = ["a", "b", "a", "c", "a"]
counts = {}
for w in words:
counts[w] = counts.get(w, 0) + 1
print(counts)
{'a': 3, 'b': 1, 'c': 1}
The first time a word shows up, get returns 0, so the word is stored with a count of 1. Every later time, it returns the count so far and the store replaces it with one more.
Common mistakes
- Using brackets for a key that may be missing.
stock["plums"]raises aKeyError. Use brackets only when you know the key is there, as with the pears. - Using the wrong default. The default is what you get back for a missing key. For counts, use 0. Forgetting it gives
None, and the line would readWe have None plums. - Expecting
getto store the default. It doesn't. Even afterstock.get("plums", 0), the key"plums"is not instock, andlen(stock)is unchanged. To store a missing key's default, assign it yourself. - Doing arithmetic on
None.stock.get("plums") + 1fails with aTypeError, whilestock.get("plums", 0) + 1is 1.
Key takeaways
d.get(key, default)returns the value forkey, ordefaultwhen it is missing.- It never raises a
KeyErrorand never adds a key. - Without a default it returns
None.
