Python Dictionaries: Master Key-Value Data Structures
Categories
Grasp the essentials of Python dictionaries. Learn to create, manipulate, and iterate through the key-value pairs for powerful data management.
Embarking on a Python journey can often feel like plunging into a labyrinth, with the multitude of diverse data structures adding to the complexity.
Among these structures, Python dictionaries offer unique capabilities that can simplify many of your programming challenges.
Yet, without a firm grasp of their use and functions, these tools can be confusing. Here, in this article, we will expose the fundamentals of Python dictionaries, from creating and manipulating them to exploring nested structures, comprehension, and distinct methods. We'll also guide you through dictionary iteration using various loops.
By the end of this guide, you will develop a better understanding of Python dictionaries.
One other important collection data type is Python lists.
As you get more into Python, the Advanced Python Concepts, like Python Operators, will become easier to understand.
But now, let’s dive into the dictionary basics first.
What Is a Python Dictionary?
Python dictionaries are powerful data structures in Python. We can define a dictionary as an unordered and mutable collection of key-value pairs. When we talk about mutability, we have to talk separately about keys and values.
The keys are immutable (strings, floats, tuples, frozensets) and unique.
On the other hand, the values might be of any data type (including list and dictionary), they are mutable, and don’t have to be unique.
Each key is associated with values.
Traditional dictionaries can be created with the following syntax, which consists of keys and values inside curly braces.
dictionary = {
"key": “value”,
"key2": “value2”,
"key3": “value3”}
Fundamentals of a Python Dictionary
Creating a Simple Python Dictionary
Creating a dictionary in Python is simple and straightforward.
As mentioned earlier, dictionaries in Python are a type of data structure for storing mutable, unordered collections of key-value pairs.
A dictionary in Python is created with key-value pairs, where each key is separated from its value by a colon (:), the items are separated by commas, and the whole thing is enclosed in curly braces {}. An empty dictionary without any items is written with just two curly braces, like this: {}.
Keys in a dictionary are unique, and the values can be of any data type: integers, strings, lists, and even other dictionaries.
Here's how you can create a basic dictionary.
# Creating a dictionary
my_dict = {
"Harry Potter": "Gryffindor",
"Ron Weasley": "Gryffindor",
"Hermione Granger": “Gryffindor”
}
print(my_dict)
Here is the output.
An Alternative Way of Creating a Dictionary in Python
In the next example, we create a simpler dictionary that associates each character with their house.
We do that with the help from the zip() function, which is generally used to combine corresponding elements from multiple lists into tuples.
In our example, we will use it to create pairs of corresponding elements from the “names” and “houses" lists.
We also use the dict() function to convert these pairs into a dictionary where the first element of each pair is a key and the second is the corresponding value.
names = ['Harry', 'Hermione', 'Ron']
houses = ['Gryffindor', 'Gryffindor', 'Gryffindor']
characters = dict(zip(names, houses))
Here is the code to see the output.
characters
Here is the output.
Creating a Nested Dictionary in Python
Now, we’ll show you a bit more complex example.
We will create a nested dictionary called “characters”. We’ll talk more about the nested dictionaries later, but for now bear us while we show you how the syntax for creating a dictionary is applied to a nested dictionary.
In this example, the key is the Harry Potter character’s name and the corresponding value is another dictionary.
This, let’s call it the value or inner dictionary, contains information about the character.
The inner dictionaries also have keys (“house”, “pet”, and “wand”), and their corresponding values (“Gryffindor”, “Hedwig”, “Holly, phoenix feather “.)
As you already know, Python dictionaries are created using curly braces {}. In the following example, the outer dictionary characters are created with three keys: “Harry”, “Hermione”, and “Ron”.
Each of these keys has a corresponding value which is another dictionary.
The syntax to define a dictionary is as follows:
my_dict = {"key1": "value1", "key2": "value2", "key3": "value3"}
Where “key1”, “key2”, and “key3” are the keys, and “value1”, “value2”, and “value3” are their corresponding values.
For example, the value of the key “Harry” is another dictionary that contains “house”, “pet”, and “wand” as keys, each with their own values.
Here is how the nested dictionary for “Harry” is defined.
"Harry": {
"house": "Gryffindor",
"pet": "Hedwig",
"wand": "Holly, phoenix feather"
}
In this dictionary, “house” is a key, and its value is “Gryffindor”. Similarly, “pet” is a key with the value “Hedwig”, and “wand” is a key with the value “Holly, phoenix feather”.
Now you are familiar with one key:value pair of characters dictionary.
Let’s create multiple pair with the following code.
characters = {
"Harry": {
"house": "Gryffindor",
"pet": "Hedwig",
"wand": "Holly, phoenix feather"
},
"Hermione": {
"house": "Gryffindor",
"pet": "Crookshanks",
"wand": "Vine wood, dragon heartstring"
},
"Ron": {
"house": "Gryffindor",
"pet": "Scabbers",
"wand": "Willow, unicorn hair"
}
}
Write the code to see the dictionary,
characters
and here is the output.
An Alternative Way of Creating a Dictionary in Python
In this example, we again leverage Python's zip() function and dictionary comprehension (we’ll talk about this in detail soon) to create a nested dictionary called “characters” from multiple lists.
Here is the code for the lists that store details about characters from Harry Potter.
names = ['Harry', 'Hermione', 'Ron']
houses = ['Gryffindor', 'Gryffindor', 'Gryffindor']
pets = ['Hedwig', 'Crookshanks', 'Scabbers']
wands = ['Holly, phoenix feather', 'Vine wood, dragon heartstring', 'Willow, unicorn hair']
In the following code, we use zip() twice:
1. Within the dictionary comprehension to bind together the corresponding elements of houses, pets, and wands
2. Outside the dictionary comprehension to associate each name with the corresponding dictionary of details.
What is a comprehension, you might ask. The expression {"house": house, "pet": pet, "wand": wand} for house, pet, wand in zip(houses, pets, wands) is a dictionary comprehension, a concise way to create dictionaries from iterables.
It generates a new dictionary for each character where the keys are “house”, “pet”, and “wand”, and the values are the corresponding elements from the “houses”, “pets”, and “wand” lists.
characters = dict(zip(names, ({"house": house, "pet": pet, "wand": wand} for house, pet, wand in zip(houses, pets, wands))))
characters
Here is the output.
Accessing Dictionary Elements
Now that we learned how to create dictionaries, the question is how do we acces the elements in the dictionary?
This is the keys’ purpose, as they are used to access the elements in the dictionary.For instance, to access Harry's house from the “characters” dictionary, we use the key “Harry”.
Here is the code.
characters["Harry"]
Here is the output.
We can also use the get() method to access elements, which returns None if the key does not exist in the dictionary.
Let’s see another example. The following code is used to access the nested dictionary for the character "Harry" in the “characters dictionary”, and then get the value of the "house" key.
In this case, characters["Harry"] accesses the dictionary of information about Harry, and ["house"] gets the value of the "house" key within Harry's dictionary.
The print() function then outputs this value.
Here is the code.
print(characters["Harry"]["house"])
Here is the output.
An Alternative Way of Accessing Dictionary Elements
We can also use the get() method to access elements, which returns None if the key does not exist in the dictionary.
The following examples will show you how to do it.
In this example, characters.get("Hermione") gets the dictionary of information about Hermione, and .get("wand") gets the value of the "wand" key within Hermione's dictionary.
The print function then outputs this value.
Here is the code.
print(characters.get("Hermione").get("wand"))
Here is the output.
You can also use get() over the square bracket notation.
print(characters["Harry"]["house"])
print(characters.get("Hermione").get("wand"))
Here is the output.
Adding Elements to the Python Dictionary
We can add new elements to the dictionary by assigning a value to a new key.
In our example, we add a new character “Draco” to the dictionary, with his house, pet, and wand details.
It is similar to the process of creating the dictionary that we earlier did.
Here is the code.
characters["Draco"] = {
"house": "Slytherin",
"pet": "Eagle Owl",
"wand": "Hawthorn, unicorn hair"
}
Here is the code for seeing the output.
characters
Here is the output.
As you can see from the output, a new character is added to the dictionary, which is Draco. It contains the elements that we earlier created.
Editing Dictionary Elements
Editing elements in a dictionary involves:
- Changing the value associated with a specific key
- Adding a new key-value pair,
- Or updating the value of an existing key.
You can't change a specific key directly, but you could accomplish that by adding a new key with the updated name and the same value and then removing the old key.
In the context of the “characters” dictionary, the following code is modifying the existing nested dictionary for the character "Ron".
Specifically, it is updating the value for the key "pet" from its current value "Scabbers" to a new value "Pigwidgeon".
Here is the code.
characters["Ron"]["pet"] = "Pigwidgeon"
Here is the output.
As you can see from the output, Ron’s pet name has changed from “Scabbers to “Pigwidgeon”.
This is an example of how you can alter the data within a nested dictionary by assigning new data to a specific key within it. In effect, the dictionary is updated to reflect that Ron's pet is now Pigwidgeon.
Removing Dictionary Elements
Removing elements from a dictionary involves deleting a key-value pair using the del keyword.
In this context, the following code is used to remove the “pet” key and its corresponding value from the nested dictionary associated with “Draco” in the “characters” dictionary.
Here is the code.
del characters["Draco"]["pet"]
Here is the output.
After this operation, when you try to access characters ["Draco"]["pet"], it will raise a KeyError since the key "pet" no longer exists in the nested dictionary for "Draco".
Let’s check this.
characters["Draco"]["pet"]
Here is the output.
Sorry! Here is the real output.
This change in the output indicates that the "pet" key and its corresponding value have been successfully removed from Draco's information.
Nested Python Dictionaries
A nested Python dictionary is like the Mines of Moria, a complex structure with multiple layers. Our Lord of the Rings-inspired example has a dictionary called “characters”, which is like the Fellowship of the Ring itself.
Each character in the Fellowship (the key in the dictionary) carries their own tale (another dictionary), housing information about their race, whether they bore the ring, and who their friends were.
To put it more precisely, a nested dictionary is essentially a dictionary within a dictionary.
This provides us with a way to store complex, structured information in a manner that is both easily readable and manipulable in Python.
So, when creating it, we effectively create a dictionary first, and then within that, we assign dictionaries as values to keys.
To make it simpler, let’s create it step by step.
Creating Nested Dictionary
Our approach will consist of two steps:
- Defining the outermost level as an empty dict object
- Add additional keys and values for each dictionary layer
By doing it this way, you will be able to grasp the layers better.
1. Define the Outermost Level
We start with this code.
characters = {}
Yes, that’s it. We can now move to the second step.
2. Add Additional Keys and Values
Here, each character's name is key in the outer dictionary, and the value is another dictionary that contains the character's race, whether they were a ring bearer, and a list of their friends.
Here is the code that does that.
characters['Frodo'] = {'race': 'Hobbit', 'ring_bearer': True, 'friends': ['Sam', 'Merry', 'Pippin']}
characters['Sam'] = {'race': 'Hobbit', 'ring_bearer': False, 'friends': ['Frodo', 'Merry', 'Pippin']}
characters['Merry'] = {'race': 'Hobbit', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Pippin']}
characters['Pippin'] = {'race': 'Hobbit', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Merry']}
characters['Aragorn'] = {'race': 'Human', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Merry', 'Pippin', 'Gandalf', 'Legolas', 'Gimli']}
characters['Legolas'] = {'race': 'Elf', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Merry', 'Pippin', 'Gandalf', 'Aragorn', 'Gimli']}
characters['Gimli'] = {'race': 'Dwarf', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Merry', 'Pippin', 'Gandalf', 'Aragorn', 'Legolas']}
characters['Gandalf'] = {'race': 'Wizard', 'ring_bearer': False, 'friends': ['Frodo', 'Sam', 'Merry', 'Pippin', 'Aragorn', 'Legolas', 'Gimli']}
Now, the “characters” dictionary contains all the necessary information about the characters from the Lord of the Rings series. Each character's information includes their race, whether they were a ring bearer and a list of their friends.
Accessing Elements in a Nested Python
This can be tricky, especially if you are not familiar with the structure. To access an element in a nested dictionary, you must first understand how to go through each level of data.
Utilizing a for loop is the most common method adopted for achieving this task.
The following code leverages for loops to access elements in a nested Python dictionary.
The outer loop goes through each key-value pair in the top-level dictionary, where the keys are referenced by 'outer_keys' and the values (which are inner dictionaries) by 'inner_dict'.
The inner loop then navigates through each key-value pair of these nested dictionaries.
If the value within the nested dictionary is of list type, another loop is utilized to print each item in the list. Otherwise, if the value is not a list, it simply prints out the key-value pairs.
Here is the code.
for outer_keys, inner_dict in characters.items(): # Iterate over outer keys
for inner_keys, values in inner_dict.items(): # Iterate over inner keys
if type(values) == list: # Check if value is list type
print(f"{outer_keys}:{inner_keys} = ", end="")
for item in values: # If so iterate over items
print(item, end=", ") # Print out items
print()
else:
print(f"{outer_keys}:{inner_keys} = {values}") # Print out key-value pairs
Here is the output.
While for loops offer a powerful way to traverse nested dictionaries, they are not the only method. Depending on your specific task, you may also use methods like dictionary comprehension, recursive functions, or built-in functions like dict.get() to access specific elements directly if you know the keys.
Dictionary Comprehension in Python
Now let’s travel from the Lord of the Rings world to back Harry Potter’s world again. We will travel these realms back and forth and use the data you’re already familiar with.
Dictionary comprehensions are like a magic wand in Python that allow us to create new dictionaries from existing ones.
They are similar to list comprehensions, but instead of creating lists, they create dictionaries.
To create a dictionary comprehension, we start with an expression followed by a for loop inside curly braces {}.
The expression consists of the key:value pairs separated by commas and is evaluated once for each item in the iterable object provided after the for loop statement.
The keys and values can be any valid expressions, including function calls or even other dictionary comprehensions!
In our Harry Potter example, the following code creates a new dictionary, “house_dict”, where each key is a character's name and each value is the house that the character belongs to. The for character, info in characters.items() part of the code is iterating over each item in the characters dictionary.
For each item, it assigns the character's name to the character and the dictionary of information about the character to info. Then, it uses the character as the key and info["house"] as the value in the new dictionary.
Here is the code.
house_dict = {character: info["house"] for character, info in characters.items()}
print(house_dict)
Here is the output.
Dictionary Methods in Python
There are several built-in methods used for working with dictionaries in Python. Here’s their overview.
clear()
This method deletes all elements from the dictionary.
The clear() method doesn't require any parameters to do that.
After executing the following code, the dictionary characters will be empty, i.e., {}.
characters.clear()
print(characters)
Here is the output.
get()
It returns the value for a key if it exists in the dictionary. If the key does not exist and a default value is provided, it returns the default value. If the key does not exist and no default value is provided, it returns None.
The get() method requires at least one parameter, the key to look for in the dictionary. An optional second parameter can provide a default value if the key is not found.
The following code prints the value corresponding to “Harry” in the characters dictionary.
print(characters.get("Harry"))
Here is the output.
Now, let’s see the value for Voldemort.
print(characters.get("Voldemort"))
Here is the output.
The output is None because Voldemort is a non-existent key in the “characters” dictionary.
The above code can be amended by adding the default value.
For example, the following code prints “Character not found” if “Voldemort” isn't key in “characters”. This is what the second argument in get() does.
print(characters.get("Voldemort", "Character not found"))
Here is the output.
items()
This method returns a view object that displays a list of the dictionary's key-value tuple pairs.
The following code prints a list-like view object of all key-value pairs in the dictionary characters.
print(characters.items())
Here is the output.
keys()
This method returns a view object that displays a list of all the keys in the dictionary.
The following code would print a list-like view object of all keys in the dictionary characters.
Here is the code.
print(characters.keys())
Here is the output.
values()
It will output a list of all the values that exist in the dictionary.
The following code would print a list-like view object of all values in the dictionary characters.
Here is the code.
print(characters.values())
Here is the output.
pop()
This method helps you delete the element from the dictionary and prints out the element that was deleted afterward.
If the key is not found, it returns the default value provided. If the key is not found and no default value is provided, it raises a KeyError.
Let’s remove Draco since he and his family were at Voldemort's side at the beginning.
print(characters.pop("Draco"))
Here is the output.
As we can see from the output, this method prints out the element that was deleted.
Great, now that we deleted him, let’s try the same with that bastard Voldemort.
By adding an error message (string) as an argument, we say that if Voldemort is not in this dictionary, the specified error message (string) is printed.
Here is the code.
print(characters.pop("Voldemort", "Character not found"))
Here is the output.
popitem()
This method removes and returns the last inserted key-value pair from the dictionary.
When a dictionary doesn't have any elements, attempting to access an item will result in a KeyError being raised.
The following code removes and print the last inserted key-value pair in the characters dictionary.
print(characters.popitem())
Since we already removed Draco, it looks like Ron will be deleted like he was eliminated at the Chess game in the Chamber of Secrets.
Here is the output.
update()
This method augments the dictionary by incorporating elements from another dictionary or from an iterable consisting of key-value pairs.
Let’s add Voldemort to our list using the update() method.
The following code would add Voldemort characters and the features of this character to our dictionary.
characters.update({"Voldemort": {"house": "Slytherin", "pet": "Nagini", "wand": "Yew, phoenix feather"}})
print(characters)
Here is the output.
As we can see, our character dictionary was updated and Voldemort was added to the dictionary.
Dictionary Iteration in Python
Dictionary iteration is the process of traversing or looping through the dictionary to access its elements, i.e., keys and values.
Python provides several ways to iterate over dictionaries, including using for loops, dictionary methods like items(), keys(), and values(), and dictionary comprehensions.
In the next sections, we will iterate over keys, values and nested values.
Iteration Over Keys
The following code block will print each key in the characters dictionary. The output will be the list of all keys in characters.
for key in characters.keys():
print(key)
Here is the output.
Iteration Over Values
The following code block will print each value in the characters dictionary. The output will be the list of all values in characters.
for value in characters.values():
print(value)
Iteration Over Nested Python Dictionary
We talked about how the key might be a dictionary. This is again such an example. To break down this inside dictionary, let’s write two for loops inside each other.
In the following code, first for loops opens the first dictionary and the second one opens the nested dictionary.
for key, value in characters.items():
print(f"key : {key} and value : {value} ")
for key,value in value.items():
print(f"Inside key : {key} and value: {value}")
Here is the output.
Bonus Section - Quiz
Now, let’s solidify what we learned together.
Quiz
- What is a Python dictionary and how is it different from other data types in Python?
- Given the dictionary student = {“name”: “John”,”'age”: 20}, how would you access the value of 'name', and how would you change the value of 'age' to 21?
- How do you add a new key-value pair, for example, “grade” = “A”, to the existing “student” dictionary?
- Consider the nested dictionary grades = {“John”: {“Math”: “A”, “English”: “B”}, “Emma”: {“Math”: “B”, “English”: “A”}}. How would you access Emma's grade in English?
- What is dictionary comprehension and how would you use it to create a new dictionary that squares all the values in the dictionary numbers = {1: 2, 2: 3, 3: 4}?
Great, now let’s see the answers.
Answers
1. In Python, a dictionary is a changeable and unordered assemblage of key-value pairs, with the stipulation that each key must be distinct. It is different from other data types in Python.
2. To access the value of 'name' from the dictionary, you would use student['name']. To change the value of 'age' to 21, you would use:
student['age'] = 21
3. To add a new key-value pair to the 'student' dictionary, you would use:
student['age'] = ‘A’
4. To access Emma's grade in English from the nested dictionary, you would use:
grades['Emma']['English']
5. Dictionary comprehension is a concise way to create dictionaries using an expression that can be conditional. To create a new dictionary that squares all the values in the dictionary numbers = {1: 2, 2: 3, 3: 4}, you would use:
{k: v**2 for k, v in numbers.items()}
Final Words
Python dictionaries are undeniably powerful tools that streamline your coding experience by offering the versatility of key-value pairs.
By mastering dictionary creation, manipulation, iteration, and the application of various methods, you're equipping yourself with a formidable weapon to tackle diverse programming challenges.
The exploration of nested dictionaries and dictionary comprehension further enriches your Python toolkit.
Remember, like any tool, the utility of dictionaries lies in practice. So, keep experimenting and applying these concepts in various scenarios. With this newfound knowledge, you're one step closer to becoming a more adept Python programmer.
Happy coding!