Chapter 6: Dictionaries
|
Source: Python Crash Course, 3rd Edition by Eric Matthes |
In this chapter you’ll learn how to use Python’s dictionaries, which allow you to connect pieces of related information. You’ll learn how to access the information once it’s in a dictionary and how to modify that information. Because dictionaries can store an almost limitless amount of information, I’ll show you how to loop through the data in a dictionary. Additionally, you’ll learn to nest dictionaries inside lists, lists inside dictionaries, and even dictionaries inside other dictionaries.
Understanding dictionaries allows you to model a variety of real-world objects more accurately. You’ll be able to create a dictionary representing a person and then store as much information as you want about that person. You can store their name, age, location, profession, and any other aspect of a person you can describe. You’ll be able to store any two kinds of information that can be matched up, such as a list of words and their meanings, a list of people’s names and their favorite numbers, a list of mountains and their elevations, and so forth.
A Simple Dictionary
Consider a game featuring aliens that can have different colors and point values. This simple dictionary stores information about a particular alien:
alien_0 = {'color': 'green', 'points': 5}
print(alien_0['color'])
print(alien_0['points'])
The dictionary alien_0 stores the alien’s color and point value. The
last two lines access and display that information:
green
5
As with most new programming concepts, using dictionaries takes practice. Once you’ve worked with dictionaries for a bit, you’ll see how effectively they can model real-world situations.
Working with Dictionaries
A dictionary in Python is a collection of key-value pairs. Each key is connected to a value, and you can use a key to access the value associated with that key. A key’s value can be a number, a string, a list, or even another dictionary. In fact, you can use any object that you can create in Python as a value in a dictionary.
In Python, a dictionary is wrapped in braces ({}) with a series of
key-value pairs inside the braces, as shown in the earlier example:
alien_0 = {'color': 'green', 'points': 5}
A key-value pair is a set of values associated with each other. When you provide a key, Python returns the value associated with that key. Every key is connected to its value by a colon, and individual key-value pairs are separated by commas. You can store as many key-value pairs as you want in a dictionary.
The simplest dictionary has exactly one key-value pair, as shown in this
modified version of the alien_0 dictionary:
alien_0 = {'color': 'green'}
This dictionary stores one piece of information about alien_0: the
alien’s color. The string 'color' is a key in this dictionary, and its
associated value is 'green'.
Accessing Values in a Dictionary
To get the value associated with a key, give the name of the dictionary and then place the key inside a set of square brackets, as shown here:
alien_0 = {'color': 'green'}
print(alien_0['color'])
This returns the value associated with the key 'color' from the
dictionary alien_0:
green
You can have an unlimited number of key-value pairs in a dictionary. For
example, here’s the original alien_0 dictionary with two key-value
pairs:
alien_0 = {'color': 'green', 'points': 5}
Now you can access either the color or the point value of alien_0. If
a player shoots down this alien, you can look up how many points they
should earn using code like this:
alien_0 = {'color': 'green', 'points': 5}
new_points = alien_0['points']
print(f"You just earned {new_points} points!")
Once the dictionary has been defined, we pull the value associated with
the key 'points' from the dictionary. This value is then assigned to
the variable new_points. The last line prints a statement about how
many points the player just earned:
You just earned 5 points!
Adding New Key-Value Pairs
Dictionaries are dynamic structures, and you can add new key-value pairs to a dictionary at any time. To add a new key-value pair, you would give the name of the dictionary followed by the new key in square brackets, along with the new value.
Let’s add two new pieces of information to the alien_0 dictionary: the
alien’s x- and y-coordinates, which will help us display the alien at a
particular position on the screen. Let’s place the alien on the left
edge of the screen, 25 pixels down from the top:
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
alien_0['x_position'] = 0
alien_0['y_position'] = 25
print(alien_0)
We start by defining the same dictionary that we’ve been working with.
We then print this dictionary, displaying a snapshot of its information.
Next, we add a new key-value pair to the dictionary: the key
'x_position' and the value 0. We do the same for the key
'y_position'. When we print the modified dictionary, we see the two
additional key-value pairs:
{'color': 'green', 'points': 5}
{'color': 'green', 'points': 5, 'x_position': 0, 'y_position': 25}
The final version of the dictionary contains four key-value pairs. The original two specify color and point value, and two more specify the alien’s position.
Dictionaries retain the order in which they were defined. When you print a dictionary or loop through its elements, you will see the elements in the same order they were added to the dictionary.
Starting with an Empty Dictionary
It’s sometimes convenient, or even necessary, to start with an empty
dictionary and then add each new item to it. To start filling an empty
dictionary, define a dictionary with an empty set of braces and then add
each key-value pair on its own line. For example, here’s how to build
the alien_0 dictionary using this approach:
alien_0 = {}
alien_0['color'] = 'green'
alien_0['points'] = 5
print(alien_0)
We first define an empty alien_0 dictionary, and then add color and
point values to it. The result is the dictionary we’ve been using in
previous examples:
{'color': 'green', 'points': 5}
Typically, you’ll use empty dictionaries when storing user-supplied data in a dictionary or when writing code that generates a large number of key-value pairs automatically.
Modifying Values in a Dictionary
To modify a value in a dictionary, give the name of the dictionary with the key in square brackets and then the new value you want associated with that key. For example, consider an alien that changes from green to yellow as a game progresses:
alien_0 = {'color': 'green'}
print(f"The alien is {alien_0['color']}.")
alien_0['color'] = 'yellow'
print(f"The alien is now {alien_0['color']}.")
We first define a dictionary for alien_0 that contains only the
alien’s color; then we change the value associated with the key
'color' to 'yellow'. The output shows that the alien has indeed
changed from green to yellow:
The alien is green.
The alien is now yellow.
For a more interesting example, let’s track the position of an alien that can move at different speeds. We’ll store a value representing the alien’s current speed and then use it to determine how far to the right the alien should move:
alien_0 = {'x_position': 0, 'y_position': 25, 'speed': 'medium'}
print(f"Original position: {alien_0['x_position']}")
# Move the alien to the right.
# Determine how far to move the alien based on its current speed.
if alien_0['speed'] == 'slow': (1)
x_increment = 1
elif alien_0['speed'] == 'medium':
x_increment = 2
else:
# This must be a fast alien.
x_increment = 3
# The new position is the old position plus the increment.
alien_0['x_position'] = alien_0['x_position'] + x_increment (2)
print(f"New position: {alien_0['x_position']}")
| 1 | An if-elif-else chain determines how far the alien should move to
the right and assigns this value to the variable x_increment. |
| 2 | The increment is added to the value of x_position, and the result
is stored back in the dictionary. |
Because this is a medium-speed alien, its position shifts two units to the right:
Original position: 0
New position: 2
By changing one value in the alien’s dictionary, you can change the overall behavior of the alien. For example, to turn this medium-speed alien into a fast alien, you would add this line:
alien_0['speed'] = 'fast'
The if-elif-else block would then assign a larger value to
x_increment the next time the code runs.
Removing Key-Value Pairs
When you no longer need a piece of information that’s stored in a
dictionary, you can use the del statement to completely remove a
key-value pair. All del needs is the name of the dictionary and the
key that you want to remove.
For example, let’s remove the key 'points' from the alien_0
dictionary, along with its value:
alien_0 = {'color': 'green', 'points': 5}
print(alien_0)
del alien_0['points'] (1)
print(alien_0)
| 1 | The del statement tells Python to delete the key 'points' from
the dictionary alien_0 and to remove the value associated with
that key as well. |
{'color': 'green', 'points': 5}
{'color': 'green'}
|
Be aware that the deleted key-value pair is removed permanently. |
A Dictionary of Similar Objects
The previous example involved storing different kinds of information about one object, an alien in a game. You can also use a dictionary to store one kind of information about many objects. For example, say you want to poll a number of people and ask them what their favorite programming language is. A dictionary is useful for storing the results of a simple poll, like this:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
As you can see, we’ve broken a larger dictionary into several lines. Each key is the name of a person who responded to the poll, and each value is their language choice. When you know you’ll need more than one line to define a dictionary, press Enter after the opening brace. Then indent the next line one level (four spaces) and write the first key-value pair, followed by a comma. From this point forward when you press Enter, your text editor should automatically indent all subsequent key-value pairs to match the first key-value pair.
Once you’ve finished defining the dictionary, add a closing brace on a new line after the last key-value pair, and indent it one level so it aligns with the keys in the dictionary. It’s good practice to include a comma after the last key-value pair as well, so you’re ready to add a new key-value pair on the next line.
|
Most editors have some functionality that helps you format extended lists and dictionaries in a similar manner to this example. Other acceptable ways to format long dictionaries are available as well, so you may see slightly different formatting in your editor, or in other sources. |
To use this dictionary, given the name of a person who took the poll, you can easily look up their favorite language:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
language = favorite_languages['sarah'].title() (1)
print(f"Sarah's favorite language is {language}.")
| 1 | We ask for the value at favorite_languages['sarah'] and assign it
to the variable language. Creating a new variable here makes for a
much cleaner print() call. |
Sarah's favorite language is C.
You could use this same syntax with any individual represented in the dictionary.
Using get() to Access Values
Using keys in square brackets to retrieve the value you’re interested in from a dictionary might cause one potential problem: if the key you ask for doesn’t exist, you’ll get an error.
Let’s see what happens when you ask for the point value of an alien that doesn’t have a point value set:
alien_0 = {'color': 'green', 'speed': 'slow'}
print(alien_0['points'])
This results in a traceback, showing a KeyError:
Traceback (most recent call last):
File "alien_no_points.py", line 2, in <module>
print(alien_0['points'])
~~~~~~~^^^^^^^^^^
KeyError: 'points'
You’ll learn more about how to handle errors like this in general in
Chapter 10. For dictionaries specifically, you can use the get() method
to set a default value that will be returned if the requested key
doesn’t exist.
The get() method requires a key as a first argument. As a second
optional argument, you can pass the value to be returned if the key
doesn’t exist:
alien_0 = {'color': 'green', 'speed': 'slow'}
point_value = alien_0.get('points', 'No point value assigned.')
print(point_value)
If the key 'points' exists in the dictionary, you’ll get the
corresponding value. If it doesn’t, you get the default value. In this
case, points doesn’t exist, and we get a clean message instead of an
error:
No point value assigned.
If there’s a chance the key you’re asking for might not exist, consider
using the get() method instead of the square bracket notation.
|
If you leave out the second argument in the call to |
Try It Yourself
6-1. Person: Use a dictionary to store information about a person you
know. Store their first name, last name, age, and the city in which they
live. You should have keys such as first_name, last_name, age, and
city. Print each piece of information stored in your dictionary.
6-2. Favorite Numbers: Use a dictionary to store people’s favorite numbers. Think of five names, and use them as keys in your dictionary. Think of a favorite number for each person, and store each as a value in your dictionary. Print each person’s name and their favorite number. For even more fun, poll a few friends and get some actual data for your program.
6-3. Glossary: A Python dictionary can be used to model an actual
dictionary. However, to avoid confusion, let’s call it a glossary. Think
of five programming words you’ve learned about in the previous chapters.
Use these words as the keys in your glossary, and store their meanings as
values. Print each word and its meaning as neatly formatted output. You
might print the word followed by a colon and then its meaning, or print
the word on one line and then print its meaning indented on a second
line. Use the newline character (\n) to insert a blank line between
each word-meaning pair in your output.
Looping Through a Dictionary
A single Python dictionary can contain just a few key-value pairs or millions of pairs. Because a dictionary can contain large amounts of data, Python lets you loop through a dictionary. Dictionaries can be used to store information in a variety of ways; therefore, several different ways exist to loop through them. You can loop through all of a dictionary’s key-value pairs, through its keys, or through its values.
Looping Through All Key-Value Pairs
Before we explore the different approaches to looping, let’s consider a new dictionary designed to store information about a user on a website. The following dictionary would store one person’s username, first name, and last name:
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
You can access any single piece of information about user_0 based on
what you’ve already learned in this chapter. But what if you wanted to
see everything stored in this user’s dictionary? To do so, you could
loop through the dictionary using a for loop:
user_0 = {
'username': 'efermi',
'first': 'enrico',
'last': 'fermi',
}
for key, value in user_0.items():
print(f"\nKey: {key}")
print(f"Value: {value}")
To write a for loop for a dictionary, you create names for the two
variables that will hold the key and value in each key-value pair. You
can choose any names you want for these two variables. This code would
work just as well if you had used abbreviations for the variable names,
like this:
for k, v in user_0.items()
The second half of the for statement includes the name of the
dictionary followed by the method items(), which returns a sequence of
key-value pairs. The for loop then assigns each of these pairs to the
two variables provided. In the preceding example, we use the variables to
print each key, followed by the associated value. The "\n" in the first
print() call ensures that a blank line is inserted before each
key-value pair in the output:
Key: username
Value: efermi
Key: first
Value: enrico
Key: last
Value: fermi
Looping through all key-value pairs works particularly well for
dictionaries like favorite_languages.py, which stores the same kind of
information for many different keys. If you loop through the
favorite_languages dictionary, you get the name of each person in the
dictionary and their favorite programming language. Because the keys
always refer to a person’s name and the value is always a language, we’ll
use the variables name and language in the loop instead of key and
value. This will make it easier to follow what’s happening inside the
loop:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name, language in favorite_languages.items():
print(f"{name.title()}'s favorite language is {language.title()}.")
This code tells Python to loop through each key-value pair in the
dictionary. As it works through each pair the key is assigned to the
variable name, and the value is assigned to the variable language.
These descriptive names make it much easier to see what the print()
call is doing.
Now, in just a few lines of code, we can display all of the information from the poll:
Jen's favorite language is Python.
Sarah's favorite language is C.
Edward's favorite language is Rust.
Phil's favorite language is Python.
This type of looping would work just as well if our dictionary stored the results from polling a thousand or even a million people.
Looping Through All the Keys in a Dictionary
The keys() method is useful when you don’t need to work with all of
the values in a dictionary. Let’s loop through the
favorite_languages dictionary and print the names of everyone who took
the poll:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name in favorite_languages.keys():
print(name.title())
This for loop tells Python to pull all the keys from the dictionary
favorite_languages and assign them one at a time to the variable
name. The output shows the names of everyone who took the poll:
Jen
Sarah
Edward
Phil
Looping through the keys is actually the default behavior when looping through a dictionary, so this code would have exactly the same output if you wrote:
for name in favorite_languages:
rather than:
for name in favorite_languages.keys():
You can choose to use the keys() method explicitly if it makes your
code easier to read, or you can omit it if you wish.
You can access the value associated with any key you care about inside the loop, by using the current key. Let’s print a message to a couple of friends about the languages they chose. We’ll loop through the names in the dictionary as we did previously, but when the name matches one of our friends, we’ll display a message about their favorite language:
favorite_languages = {
# --snip--
}
friends = ['phil', 'sarah']
for name in favorite_languages.keys():
print(f"Hi {name.title()}.")
if name in friends: (1)
language = favorite_languages[name].title() (2)
print(f"\t{name.title()}, I see you love {language}!")
| 1 | Inside the loop, we check whether the name we’re working with is in
the list friends. |
| 2 | If it is, we determine the person’s favorite language using the name
of the dictionary and the current value of name as the key. |
Everyone’s name is printed, but our friends receive a special message:
Hi Jen.
Hi Sarah.
Sarah, I see you love C!
Hi Edward.
Hi Phil.
Phil, I see you love Python!
You can also use the keys() method to find out if a particular person
was polled. This time, let’s find out if Erin took the poll:
favorite_languages = {
# --snip--
}
if 'erin' not in favorite_languages.keys():
print("Erin, please take our poll!")
The keys() method isn’t just for looping: it actually returns a
sequence of all the keys, and the if statement simply checks if
'erin' is in this sequence. Because she’s not, a message is printed
inviting her to take the poll:
Erin, please take our poll!
Looping Through a Dictionary’s Keys in a Particular Order
Looping through a dictionary returns the items in the same order they were inserted. Sometimes, though, you’ll want to loop through a dictionary in a different order.
One way to do this is to sort the keys as they’re returned in the for
loop. You can use the sorted() function to get a copy of the keys in
order:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
for name in sorted(favorite_languages.keys()):
print(f"{name.title()}, thank you for taking the poll.")
This for statement is like other for statements, except that we’ve
wrapped the sorted() function around the dictionary.keys() method.
This tells Python to get all the keys in the dictionary and sort them
before starting the loop. The output shows everyone who took the poll,
with the names displayed in order:
Edward, thank you for taking the poll.
Jen, thank you for taking the poll.
Phil, thank you for taking the poll.
Sarah, thank you for taking the poll.
Looping Through All Values in a Dictionary
If you are primarily interested in the values that a dictionary
contains, you can use the values() method to return a sequence of
values without any keys. For example, say we simply want a list of all
languages chosen in our programming language poll, without the name of
the person who chose each language:
favorite_languages = {
'jen': 'python',
'sarah': 'c',
'edward': 'rust',
'phil': 'python',
}
print("The following languages have been mentioned:")
for language in favorite_languages.values():
print(language.title())
The for statement here pulls each value from the dictionary and assigns
it to the variable language. When these values are printed, we get a
list of all chosen languages:
The following languages have been mentioned:
Python
C
Rust
Python
This approach pulls all the values from the dictionary without checking for repeats. This might work fine with a small number of values, but in a poll with a large number of respondents, it would result in a very repetitive list. To see each language chosen without repetition, we can use a set. A set is a collection in which each item must be unique:
favorite_languages = {
# --snip--
}
print("The following languages have been mentioned:")
for language in set(favorite_languages.values()):
print(language.title())
When you wrap set() around a collection of values that contains
duplicate items, Python identifies the unique items in the collection
and builds a set from those items. Here we use set() to pull out the
unique languages in favorite_languages.values().
The result is a nonrepetitive list of languages that have been mentioned by people taking the poll:
The following languages have been mentioned:
Python
C
Rust
|
You can build a set directly using braces and separating the elements with commas:
It’s easy to mistake sets for dictionaries because they’re both wrapped in braces. When you see braces but no key-value pairs, you’re probably looking at a set. Unlike lists and dictionaries, sets do not retain items in any specific order. |
Try It Yourself
6-4. Glossary 2: Now that you know how to loop through a dictionary,
clean up the code from Exercise 6-3 by replacing your series of
print() calls with a loop that runs through the dictionary’s keys and
values. When you’re sure that your loop works, add five more Python terms
to your glossary. When you run your program again, these new words and
meanings should automatically be included in the output.
6-5. Rivers: Make a dictionary containing three major rivers and the
country each river runs through. One key-value pair might be
'nile': 'egypt'. Use a loop to print a sentence about each river,
such as The Nile runs through Egypt. Use a loop to print the name of
each river included in the dictionary. Use a loop to print the name of
each country included in the dictionary.
6-6. Polling: Use the code in favorite_languages.py. Make a list of
people who should take the favorite languages poll. Include some names
that are already in the dictionary and some that are not. Loop through
the list of people who should take the poll. If they have already taken
the poll, print a message thanking them for responding. If they have not
yet taken the poll, print a message inviting them to take the poll.
Nesting
Sometimes you’ll want to store multiple dictionaries in a list, or a list of items as a value in a dictionary. This is called nesting. You can nest dictionaries inside a list, a list of items inside a dictionary, or even a dictionary inside another dictionary. Nesting is a powerful feature, as the following examples will demonstrate.
A List of Dictionaries
The alien_0 dictionary contains a variety of information about one
alien, but it has no room to store information about a second alien,
much less a screen full of aliens. How can you manage a fleet of aliens?
One way is to make a list of aliens in which each alien is a dictionary
of information about that alien. For example, the following code builds
a list of three aliens:
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2] (1)
for alien in aliens:
print(alien)
| 1 | We store each of the three dictionaries in a list called aliens. |
{'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 10}
{'color': 'red', 'points': 15}
A more realistic example would involve more than three aliens with code
that automatically generates each alien. In the following example, we
use range() to create a fleet of 30 aliens:
# Make an empty list for storing aliens.
aliens = []
# Make 30 green aliens.
for alien_number in range(30): (1)
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'} (2)
aliens.append(new_alien) (3)
# Show the first 5 aliens.
for alien in aliens[:5]: (4)
print(alien)
print("...")
# Show how many aliens have been created.
print(f"Total number of aliens: {len(aliens)}")
| 1 | The range() function returns a series of numbers that tells Python
how many times we want the loop to repeat. |
| 2 | Each time the loop runs, we create a new alien. |
| 3 | Each new alien is appended to the list aliens. |
| 4 | We use a slice to print the first five aliens. |
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
...
Total number of aliens: 30
These aliens all have the same characteristics, but Python considers each one a separate object, which allows us to modify each alien individually.
How might you work with a group of aliens like this? Imagine that one
aspect of a game has some aliens changing color and moving faster as the
game progresses. When it’s time to change colors, we can use a for
loop and an if statement to change the color of the aliens. For
example, to change the first three aliens to yellow, medium-speed aliens
worth 10 points each, we could do this:
# Make an empty list for storing aliens.
aliens = []
# Make 30 green aliens.
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
for alien in aliens[:3]:
if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10
# Show the first 5 aliens.
for alien in aliens[:5]:
print(alien)
print("...")
Because we want to modify the first three aliens, we loop through a
slice that includes only the first three aliens. All of the aliens are
green now, but that won’t always be the case, so we write an if
statement to make sure we’re only modifying green aliens. If the alien
is green, we change the color to 'yellow', the speed to 'medium',
and the point value to 10:
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
...
You could expand this loop by adding an elif block that turns yellow
aliens into red, fast-moving ones worth 15 points each. Without showing
the entire program again, that loop would look like this:
for alien in aliens[0:3]:
if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10
elif alien['color'] == 'yellow':
alien['color'] = 'red'
alien['speed'] = 'fast'
alien['points'] = 15
It’s common to store a number of dictionaries in a list when each
dictionary contains many kinds of information about one object. For
example, you might create a dictionary for each user on a website, and
store the individual dictionaries in a list called users. All of the
dictionaries in the list should have an identical structure, so you can
loop through the list and work with each dictionary object in the same
way.
A List in a Dictionary
Rather than putting a dictionary inside a list, it’s sometimes useful to put a list inside a dictionary. For example, consider how you might describe a pizza that someone is ordering. If you were to use only a list, all you could really store is a list of the pizza’s toppings. With a dictionary, a list of toppings can be just one aspect of the pizza you’re describing.
In the following example, two kinds of information are stored for each
pizza: a type of crust and a list of toppings. The list of toppings is a
value associated with the key 'toppings'. To use the items in the
list, we give the name of the dictionary and the key 'toppings', as we
would any value in the dictionary. Instead of returning a single value,
we get a list of toppings:
# Store information about a pizza being ordered.
pizza = {
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}
# Summarize the order.
print(f"You ordered a {pizza['crust']}-crust pizza " (1)
"with the following toppings:")
for topping in pizza['toppings']: (2)
print(f"\t{topping}")
| 1 | We summarize the order before building the pizza. When you need to
break up a long line in a print() call, Python will automatically
combine all of the strings it finds inside the parentheses. |
| 2 | To print the toppings, we write a for loop. To access the list of
toppings, we use the key 'toppings', and Python grabs the list of
toppings from the dictionary. |
You ordered a thick-crust pizza with the following toppings:
mushrooms
extra cheese
You can nest a list inside a dictionary anytime you want more than one
value to be associated with a single key in a dictionary. In the earlier
example of favorite programming languages, if we were to store each
person’s responses in a list, people could choose more than one favorite
language. When we loop through the dictionary, the value associated with
each person would be a list of languages rather than a single language.
Inside the dictionary’s for loop, we use another for loop to run
through the list of languages associated with each person:
favorite_languages = {
'jen': ['python', 'rust'],
'sarah': ['c'],
'edward': ['rust', 'go'],
'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items(): (1)
print(f"\n{name.title()}'s favorite languages are:")
for language in languages: (2)
print(f"\t{language.title()}")
| 1 | When we loop through the dictionary, we use the variable name
languages to hold each value from the dictionary, because we know
that each value will be a list. |
| 2 | Inside the main dictionary loop, we use another for loop to run
through each person’s list of favorite languages. |
Now each person can list as many favorite languages as they like:
Jen's favorite languages are:
Python
Rust
Sarah's favorite languages are:
C
Edward's favorite languages are:
Rust
Go
Phil's favorite languages are:
Python
Haskell
To refine this program even further, you could include an if statement
at the beginning of the dictionary’s for loop to see whether each
person has more than one favorite language by examining the value of
len(languages). If a person has more than one favorite, the output
would stay the same. If the person has only one favorite language, you
could change the wording to reflect that. For example, you could say,
"Sarah’s favorite language is C."
|
You should not nest lists and dictionaries too deeply. If you’re nesting items much deeper than what you see in the preceding examples, or if you’re working with someone else’s code with significant levels of nesting, there’s most likely a simpler way to solve the problem. |
A Dictionary in a Dictionary
You can nest a dictionary inside another dictionary, but your code can get complicated quickly when you do. For example, if you have several users for a website, each with a unique username, you can use the usernames as the keys in a dictionary. You can then store information about each user by using a dictionary as the value associated with their username. In the following listing, we store three pieces of information about each user: their first name, last name, and location:
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}
for username, user_info in users.items(): (1)
print(f"\nUsername: {username}") (2)
full_name = f"{user_info['first']} {user_info['last']}" (3)
location = user_info['location']
print(f"\tFull name: {full_name.title()}") (4)
print(f"\tLocation: {location.title()}")
| 1 | We loop through the users dictionary. Python assigns each key to
the variable username, and the dictionary associated with each
username is assigned to the variable user_info. |
| 2 | Once inside the main dictionary loop, we print the username. |
| 3 | We start accessing the inner dictionary. The variable user_info
has three keys: 'first', 'last', and 'location'. We use each
key to generate a neatly formatted full name and location. |
| 4 | We print a summary of what we know about each user. |
Username: aeinstein
Full name: Albert Einstein
Location: Princeton
Username: mcurie
Full name: Marie Curie
Location: Paris
Notice that the structure of each user’s dictionary is identical.
Although not required by Python, this structure makes nested
dictionaries easier to work with. If each user’s dictionary had
different keys, the code inside the for loop would be more
complicated.
Try It Yourself
6-7. People: Start with the program you wrote for Exercise 6-1. Make
two new dictionaries representing different people, and store all three
dictionaries in a list called people. Loop through your list of
people. As you loop through the list, print everything you know about
each person.
6-8. Pets: Make several dictionaries, where each dictionary represents
a different pet. In each dictionary, include the kind of animal and the
owner’s name. Store these dictionaries in a list called pets. Next,
loop through your list and as you do, print everything you know about
each pet.
6-9. Favorite Places: Make a dictionary called favorite_places.
Think of three names to use as keys in the dictionary, and store one to
three favorite places for each person. To make this exercise a bit more
interesting, ask some friends to name a few of their favorite places.
Loop through the dictionary, and print each person’s name and their
favorite places.
6-10. Favorite Numbers: Modify your program from Exercise 6-2 so each person can have more than one favorite number. Then print each person’s name along with their favorite numbers.
6-11. Cities: Make a dictionary called cities. Use the names of
three cities as keys in your dictionary. Create a dictionary of
information about each city and include the country that the city is in,
its approximate population, and one fact about that city. The keys for
each city’s dictionary should be something like country, population,
and fact. Print the name of each city and all of the information you
have stored about it.
6-12. Extensions: We’re now working with examples that are complex enough that they can be extended in any number of ways. Use one of the example programs from this chapter, and extend it by adding new keys and values, changing the context of the program, or improving the formatting of the output.
Summary
In this chapter, you learned how to define a dictionary and how to work with the information stored in a dictionary. You learned how to access and modify individual elements in a dictionary, and how to loop through all of the information in a dictionary. You learned to loop through a dictionary’s key-value pairs, its keys, and its values. You also learned how to nest multiple dictionaries in a list, nest lists in a dictionary, and nest a dictionary inside a dictionary.
In the next chapter you’ll learn about while loops and how to accept
input from people who are using your programs. This will be an exciting
chapter, because you’ll learn to make all of your programs interactive:
they’ll be able to respond to user input.
Applied Exercises: Ch 6 — Dictionaries
These exercises cover the same concepts as the chapter but use context
from real infrastructure, network security, and language learning work.
Save each as a separate .py file using lowercase and underscores, e.g.
ise_node_info.py.
Domus Digitalis / Homelab
D6-1. Node Profile: Create a dictionary called node representing one
of your Domus Digitalis hosts (e.g., kvm-01). Include keys for
hostname, os, role, ip, and vlan. Print each key-value pair
with a label.
D6-2. VLAN Registry: Create a dictionary called vlan_registry where
keys are VLAN IDs (as strings or integers) and values are VLAN names
(e.g., 100: 'INFRA'). Use items() to loop through and print each
VLAN ID and name. Then use sorted() to print them in numeric order.
D6-3. Stack Info: Create a dictionary called stack where each key is
a service name and each value is a dictionary containing host,
port, and status. Include at least four services (e.g., Vault,
FreeIPA, Wazuh, Gitea). Loop through the stack and print a formatted
summary for each service.
D6-4. BGP Peers: Create a dictionary called bgp_peers where each
key is a peer name (e.g., 'ifog', 'route64') and each value is a
list containing the peer’s ASN and tunnel IP. Loop through the
dictionary and print a summary for each peer. Use get() to safely
retrieve an optional 'description' key that may not exist on all
peers.
D6-5. Fleet Inventory: Create an empty list called fleet. Use a
loop and range() to generate five node dictionaries, each with keys
id, hostname, and status (all initially 'up'). Append each to
the fleet list. Then loop through the first three nodes and change their
status to 'maintenance'. Print all five nodes.
CHLA / ISE / Network Security
C6-1. ISE Node Profile: Create a dictionary called ise_node
representing your production ISE node. Include keys for hostname,
role, version, persona, and ip. Print each piece of information
with a label.
C6-2. Policy Set Map: Create a dictionary called policy_sets where
each key is a policy set name and each value is a dictionary containing
auth_protocol, condition, and result. Include at least three
policy sets. Loop through the dictionary using items() and print a
formatted summary for each.
C6-3. Syslog Severity Labels: Create a dictionary called
syslog_levels where keys are integers 0–7 and values are the syslog
severity label strings (Emergency through Debug). Loop through the
dictionary in sorted key order and print each level and label. Use
get() to safely look up a level that may not exist and print a default
message if it doesn’t.
C6-4. Pipeline Stages: Create a dictionary called pipeline where
each key is a stage name and each value is a list of log types processed
at that stage. Include at least three stages (e.g., 'ingest',
'enrich', 'route'). Loop through the pipeline and for each stage,
print the stage name followed by each log type on its own indented line.
C6-5. Endpoint Group Registry: Create a dictionary called endpoints
where each key is an endpoint group name and each value is a dictionary
containing vlan, acl, and description. Add at least three groups.
Loop through the dictionary and print a formatted summary for each
group. Then add a new group dynamically and confirm it appears in the
output.
General Sysadmin / Linux
L6-1. Service Profile: Create a dictionary called service
representing one systemd service you manage. Include keys for name,
state, enabled, pid, and description. Print each piece of
information with a label.
L6-2. Package Versions: Create a dictionary called packages where
keys are package names and values are installed version strings. Use
sorted() to loop through and print each package and version in
alphabetical order. Use get() to safely check for a package that may
not be in the dictionary.
L6-3. Mount Points: Create a dictionary called mounts where each
key is a mount point path and each value is a dictionary containing
device, fstype, and usage_percent. Include at least four mount
points. Loop through the dictionary and print a formatted summary. Flag
any mount point with usage_percent above 80.
L6-4. Cron Job Registry: Create a dictionary called cron_jobs where
each key is a job name and each value is a list containing the schedule
string and the command. Loop through the dictionary using items() and
print each job name, schedule, and command on labeled lines.
L6-5. User Roles: Create a dictionary called user_roles where keys
are usernames and values are lists of roles assigned to that user.
Include at least four users. Loop through the dictionary and for each
user, print their username followed by each role on its own indented
line. Check whether a specific user has the 'sudo' role using in.
Spanish / DELE C2
E6-1. Vocabulary Dictionary: Create a dictionary called vocabulario
where keys are Spanish words from your Don Quijote reading and values
are their English definitions. Include at least six words. Print each
word and definition in a formatted way, with a blank line between
entries.
E6-2. Chapter Notes: Create a dictionary called notas_capitulos
where keys are chapter numbers (integers) and values are dictionaries
containing tema (main theme), personajes (list of characters
mentioned), and vocabulario_nuevo (list of new words). Include at
least three chapters. Loop through and print a formatted summary of each
chapter’s notes.
E6-3. Grammar Topics: Create a dictionary called gramatica where
keys are grammar topic names (e.g., 'subjuntivo', 'perífrasis') and
values are lists of example sentences. Loop through the dictionary and
for each topic, print the topic name followed by each example on its own
indented line.
E6-4. DELE Study Tracker: Create a dictionary called progreso where
keys are DELE skill areas (e.g., 'comprensión lectora',
'expresión escrita') and values are dictionaries containing
completado (boolean), puntuación (score out of 100), and notas
(a string). Loop through and print a formatted summary. Use get() to
safely retrieve an optional 'siguiente_paso' key that may not exist on
all entries.
E6-5. Author Profiles: Create a dictionary called autores where keys
are author names and values are dictionaries containing época,
obras_principales (a list), and estilo. Include Cervantes and at
least two other Spanish-language authors. Loop through and print a
formatted profile for each author, including each main work on its own
indented line.