Walking a Dictionary
Once a dictionary holds data, two things come up constantly: going through all of it, and asking for a key that might not be there. Python has a clean way to do both, and a crash, the KeyError, for the moment you forget the second one.
Think of asking a hotel receptionist for a guest's room. A good receptionist says "no guest by that name" instead of fainting. A dictionary lookup with square brackets is the fainting kind; this page introduces the calm kind.
Walking the Keys
A for loop over a dictionary gives you its keys, one per round, in the order they were added. From each key you can reach its value with square brackets.
phones = {"Anna": "555-0101", "Omar": "555-0142", "Lena": "555-0177"}
for name in phones:
print(name, phones[name])
Anna 555-0101 Omar 555-0142 Lena 555-0177
Keys and Values Together
The items method gives each entry as a pair of key and value. Put two names after for, separated by a comma, and Python hands the key to the first and the value to the second in every round. This is the usual way to write any report over a dictionary. The two-names trick has a name, unpacking, and the next topic explains how it works.
phones = {"Anna": "555-0101", "Omar": "555-0142", "Lena": "555-0177"}
for name, number in phones.items():
print(f"{name}: {number}")
Anna: 555-0101 Omar: 555-0142 Lena: 555-0177
If you only need the values, values gives just those.
KeyError
Ask for a key that is not in the dictionary with square brackets, and Python stops with a KeyError. The last line of the message is simply the missing key, in quotes. Nothing is wrong with the dictionary; that one key is not there.
>>> phones = {"Anna": "555-0101", "Omar": "555-0142"}
>>> phones["Zoe"]
Traceback (most recent call last):
File "<python-input-1>", line 1, in <module>
phones["Zoe"]
~~~~~~^^^^^^^
KeyError: 'Zoe'
The Calm Lookup: get
The get method looks a key up without crashing. If the key exists, it gives the value. If not, it gives None, or a default you choose as the second argument. get never adds the key; it only reads. When you need to know first, in answers whether a key is present.
>>> phones.get("Anna")
'555-0101'
>>> phones.get("Zoe")
>>> phones.get("Zoe", "unknown")
'unknown'
>>> "Zoe" in phones
False
The second line printed nothing because the result was None, and the prompt shows nothing for None.
- "Looping over a dictionary gives its values." A plain loop gives the keys. Use
valuesfor values, oritemsfor both. - "get adds the missing key." It only reads. The dictionary is exactly the same afterwards.
- "A KeyError means the dictionary is broken." It means one key was missing. Check the spelling, or use get with a default.
- Data from outside is often incomplete. get with a sensible default is the first line of defence against it.
for key, value in d.items()is how nearly every report over a dictionary is written, in every Python project.
Knowledge Check
What does for name in phones: give on each round, when phones is a dictionary?
- Each value, which here is a phone number
- Each key, which here is a person's name
- Each key and value together as a pair
- The position of each entry, counting from 0
What does phones.get("Zoe", "unknown") give when Zoe is not a key?
- A KeyError, because Zoe is missing from phones
- The text unknown, the default that was passed
- None, whatever second value was passed to get
- A new entry for Zoe, stored with the value unknown
What does the error KeyError: 'Zoe' tell you?
- The dictionary is empty, so there are no keys in it to look up yet
- The key Zoe exists but its value is set to None
- The name phones was never given a value anywhere
- The key Zoe was asked for with square brackets and is not there
What do the two names in for name, number in phones.items(): receive?
- Two separate dictionaries, split from phones
- The first and the last entry of the dictionary
- The key and the value of one entry, each round
- Two copies of the key, for comparing with each other
You got correct