Dictionary comprehensions are a concise and quick way to create, transform, and filter dictionaries in Python. They can significantly enhance your code’s conciseness and readability compared to using regular for
loops to process your dictionaries.
Understanding dictionary comprehensions is crucial for you as a Python developer because they’re a Pythonic tool for dictionary manipulation and can be a valuable addition to your programming toolkit.
In this tutorial, you’ll learn how to:
- Create dictionaries using dictionary comprehensions
- Transform existing dictionaries with comprehensions
- Filter key-value pairs from dictionaries using conditionals
- Decide when to use dictionary comprehensions
To get the most out of this tutorial, you should be familiar with basic Python concepts, such as for
loops, iterables, and dictionaries, as well as list comprehensions.
Get Your Code: Click here to download the free sample code that you’ll use to learn about dictionary comprehensions in Python.
Take the Quiz: Test your knowledge with our interactive “Python Dictionary Comprehensions: How and When to Use Them” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Python Dictionary Comprehensions: How and When to Use ThemIn this quiz, you'll test your understanding of Python dictionary comprehensions. Dictionary comprehensions are a concise and quick way to create, transform, and filter dictionaries in Python, and can significantly enhance your code's conciseness and readability.
Creating and Transforming Dictionaries in Python
In Python programming, you’ll often need to create, populate, and transform dictionaries. To do this, you can use dictionary literals, the dict()
constructor, and for
loops. In the following sections, you’ll take a quick look at how to use these tools. You’ll also learn about dictionary comprehensions, which are a powerful way to manipulate dictionaries in Python.
Creating Dictionaries With Literals and dict()
To create new dictionaries, you can use literals. A dictionary literal is a series of key-value pairs enclosed in curly braces. The syntax of a dictionary literal is shown below:
{key_1: value_1, key_2: value_2,..., key_N: value_N}
The keys must be hashable objects and are commonly strings. The values can be any Python object, including other dictionaries. Here’s a quick example of a dictionary:
>>> likes = {"color": "blue", "fruit": "apple", "pet": "dog"}
>>> likes
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog'}
>>> likes["hobby"] = "guitar"
>>> likes
{'color': 'blue', 'fruit': 'apple', 'pet': 'dog', 'hobby': 'guitar'}
In this example, you create dictionary key-value pairs that describe things people often like. The keys and values of your dictionary are string objects. You can add new pairs to the dictionary using the dict[key] = value
syntax.
Note: To learn more about dictionaries, check out the Dictionaries in Python tutorial.
You can also create new dictionaries using the dict()
constructor:
>>> dict(apple=0.40, orange=0.35, banana=0.25)
{'apple': 0.4, 'orange': 0.35, 'banana': 0.25}
In this example, you create a new dictionary using dict()
with keyword arguments. In this case, the keys are strings and the values are floating-point numbers. It’s important to note that the dict()
constructor is only suitable for those cases where the dictionary keys can be strings that are valid Python identifiers.
Using for
Loops to Populate Dictionaries
Sometimes, you need to start with an empty dictionary and populate it with key-value pairs dynamically. To do this, you can use a for
loop. For example, say that you want to create a dictionary in which keys are integer numbers and values are powers of 2
.
Here’s how you can do this with a for
loop:
>>> powers_of_two = {}
>>> for integer in range(1, 10):
... powers_of_two[integer] = 2**integer
...
>>> powers_of_two
{1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 256, 9: 512}
In this example, you create an empty dictionary using an empty pair of curly braces. Then, you run a loop over a range of integer numbers from 1
to 9
. Inside the loop, you populate the dictionary with the integer numbers as keys and powers of two as values.
The loop in this example is readable and clear. However, you can also use dictionary comprehension to create and populate a dictionary like the one shown above.
Introducing Dictionary Comprehensions
Dictionary comprehensions allow you to build dictionaries with a one-line for
loop. If you’re familiar with list comprehensions, then you’ll quickly grasp dictionary comprehensions. Both constructs have similar syntax. The main difference is that dictionary comprehensions use curly braces instead of square brackets. Additionally, the comprehension expression must include a key and a value separated by a colon.
Here’s the syntax for a dictionary comprehension:
{key: value for member in iterable [if condition]}
A dictionary comprehension returns a new dictionary. To build this dictionary, you compute the key-value pairs from the items of an input iterable. Note that the syntax includes an optional conditional at the end, which you can use to filter existing dictionaries.
The comprehension syntax includes four elements:
- Enclosing brackets: Curly braces (
{}
) are used for dictionary comprehensions. - The comprehension expression: An expression that provides a value in each iteration. In dictionary comprehension, the expression must provide the key and its corresponding value,
key: value
. Both elements can be expressions. - The current
member
: This is the current item or value in the iterable. - The
iterable
: This can be any Python iterable object, including a list, tuple, set, generator, or similar.
The following code shows how you can build the power_of_two
dictionary using a comprehension:
>>> power_of_two = {integer: 2**integer for integer in range(1, 10)}
>>> power_of_two
{1: 2, 2: 4, 3: 8, 4: 16, 5: 32, 6: 64, 7: 128, 8: 256, 9: 512}
In this example, integer: 2**integer
is the comprehension expression, integer
is the current member, and range(1, 10)
is the iterable.
Here’s a diagram that illustrates the process of converting your loop from the previous section into the equivalent dictionary comprehension:
As you can see, with a couple of movements and the addition of the enclosing curly braces, your comprehension is complete.
Comprehensions can also have more than one for
clause. When they do, the leftmost for
iterates over the outer collection, the next for
from left to right iterates over the first nesting level, and so on.
To illustrate, say that you have a list of lists. Each nested list contains numbers. You want to create a dictionary that maps numbers to their square values. You can use a comprehension with two for
clauses as shown below:
>>> matrix = [
... [9, 3, 8, 3],
... [4, 5, 2, 8],
... [6, 4, 3, 1],
... [1, 0, 4, 5],
... ]
>>> {value: value**2 for row in matrix for value in row}
{9: 81, 3: 9, 8: 64, 4: 16, 5: 25, 2: 4, 6: 36, 1: 1, 0: 0}
In this example, the first for
loop iterates over the rows of your matrix. The second for
loop iterates over the number of each row. As a result, you get a dictionary that maps numbers to their square values. Even though this syntax works, it can make your comprehensions difficult to read and understand.
It’s important to note that in this example, instead of having 16 key-value pairs, you end up with only nine. This is because dictionary keys are unique. When the key is duplicated, the new value overrides the previous one. In this example, this behavior doesn’t cause issues because the values will always be the square of their corresponding keys.
Leveraging Dictionary Comprehensions in Python
With dictionary comprehensions, you can create new dictionaries, transform existing ones, and even filter key-value pairs. In the following sections, you’ll learn how to use dictionary comprehension to approach all these use cases. To kick things off, you’ll start by learning how to create new dictionaries from existing iterables.
Creating Dictionaries From Iterables
Sometimes, you have an iterable of data and want to create a dictionary by using the data items to generate the keys and values, while also applying some transformation to the original data. For a quick example, say that you have a list of fruits and want to create a dictionary where the keys are the fruit names displayed in uppercase, and the values represent the number of letters in each name:
>>> fruits = ["apple", "banana", "cherry"]
>>> {fruit.upper(): len(fruit) for fruit in fruits}
{'APPLE': 5, 'BANANA': 6, 'CHERRY': 6}
In this example, you apply transformations to generate the keys and values. In real-world programming, you may often need to apply transformations to generate the values or the keys.
Consider the following example that creates a dictionary with lowercase letters as keys and their Unicode code points as values:
>>> from string import ascii_lowercase
>>> {letter: ord(letter) for letter in ascii_lowercase}
{
'a': 97,
'b': 98,
'c': 99,
'd': 100,
'e': 101,
...
'z': 122,
}
In this example, you generate the dictionary’s values by running a transformation on the provided items. You use the data items directly to provide the keys.
Sometimes, you have two data sequences and want to map each item in the first sequence to the corresponding item in the second. In this case, you can use the following code:
>>> parts = [
... "CPU",
... "GPU",
... "Motherboard",
... "RAM",
... "SSD",
... "Power Supply",
... "Case",
... "Cooling Fan"
... ]
>>> stocks = [15, 8, 12, 30, 25, 10, 5, 20]
>>> {part: stock for part, stock in zip(parts, stocks)}
{
'CPU': 15,
'GPU': 8,
'Motherboard': 12,
'RAM': 30,
'SSD': 25,
'Power Supply': 10,
'Case': 5,
'Cooling Fan': 20
}
In this example, you use the built-in zip()
function to create pairs of items. This function takes two or more iterables as arguments and yields tuples of items by getting one item from each iterable.
In practice, when you need to create a dictionary from two sequences without applying any transformation on the data items, you can use the following code instead of a comprehension:
>>> dict(zip(parts, stocks))
{
'CPU': 15,
'GPU': 8,
'Motherboard': 12,
'RAM': 30,
'SSD': 25,
'Power Supply': 10,
'Case': 5,
'Cooling Fan': 20
}
This way of creating a dictionary from two sequences is pretty Pythonic and straightforward. You don’t need a comprehension. However, if you need to transform the data somehow, then you’d benefit from using a comprehension.
For example, say that you have a third list containing the prices of each computer part. You want to create a dictionary that holds the parts as keys and their costs as values. In this situation, you can’t use the trick above. You need to use a comprehension:
>>> part_costs = [250, 500, 150, 80, 100, 120, 70, 25]
>>> {
... part: stock * cost
... for part, stock, cost in zip(parts, stocks, part_costs)
... }
{
'CPU': 3750,
'GPU': 4000,
'Motherboard': 1800,
'RAM': 2400,
'SSD': 2500,
'Power Supply': 1200,
'Case': 350,
'Cooling Fan': 500,
}
In this example, using zip()
combined with dict()
doesn’t provide a suitable solution for building the dictionary because you need to compute the values. This is when a comprehension comes in handy, as it allows you to handle the calculation of values.
Transforming Existing Dictionaries
You can also use comprehensions to transform the keys or values of existing dictionaries. A typical example is when you need to swap keys and values.
For example, say that you have a dictionary containing computer parts that map to part codes, and you want an opposite configuration. In this situation, you can use a dictionary comprehension to swap the keys and values:
>>> parts = {
... "CPU": 10021,
... "GPU": 10022,
... "Motherboard": 10023,
... "RAM": 10024,
... "SSD": 10025,
... "Power Supply": 10027,
... "Case": 10026,
... "Cooling Fan": 10025,
... }
>>> {value: key for key, value in parts.items()}
{
10021: 'CPU',
10022: 'GPU',
10023: 'Motherboard',
10024: 'RAM',
10025: 'Cooling Fan',
10027: 'Power Supply',
10026: 'Case'
}
In this comprehension, you use the .items()
method on the parts
dictionary to access the key-value pairs. Then, you have two loop variables, one for the keys and one for the values. In the comprehension expression, you swap the keys and values.
Note: It’s important to note that in order for you to swap the keys and values of a dictionary, you need to have values that are hashable objects. Also, the values must be unique, or you’ll end up losing part of the data corresponding to the duplicate values.
You can get the same result using the following code that combines dict()
and zip()
with the .values()
and .keys()
dictionary methods:
>>> dict(zip(parts.values(), parts.keys()))
{
10021: 'CPU',
10022: 'GPU',
10023: 'Motherboard',
10024: 'RAM',
10025: 'Cooling Fan',
10027: 'Power Supply',
10026: 'Case'
}
In this example, you use a combination of function and method calls instead of a comprehension. The result is the same as with a comprehension.
Note: To learn more about dictionary iteration, check out the How to Iterate Through a Dictionary in Python tutorial.
As another example, say that you have a dictionary of fruits and their prices, and you need to decrease the prices by 5%. You can do this with a comprehension:
>>> fruits = {
... "apple": 1.00,
... "banana": 0.50,
... "cherry": 2.00,
... }
>>> {fruit: round(price * 0.95, 2) for fruit, price in fruits.items()}
{'apple': 0.95, 'banana': 0.48, 'cherry': 1.90}
In this example, you transform the values of the original dictionary. Now, you have a new dictionary with prices that are 5% lower.
You can apply the transformation to just the keys, or both the values and the keys, depending on what you need.
Filtering Items From Dictionaries
Dictionary comprehensions also allow you to use a conditional at the end of their syntax. This conditional will enable you to create dictionaries by filtering existing data. You can use the conditional syntax with both keys and values.
Here’s an example that filters a dictionary of numbers by their values to create a dictionary of even numbers:
>>> numbers = {"one": 1, "two": 2, "three": 3, "four": 4, "five": 5}
>>> {key: value for key, value in numbers.items() if value % 2 == 0}
{'two': 2, 'four': 4}
The conditional at the end of the comprehension filters odd numbers from the original dictionary. As a result, you get a dictionary of even numbers.
To learn how to filter a dictionary by keys, say that you have a dictionary that maps postal codes to towns, and you need to filter the dictionary to get the towns in a range of postal codes:
>>> codes = {
... "1001": "Townsville",
... "1002": "Lakeview",
... "1003": "Mountainview",
... "1101": "Riverside",
... "1102": "Hilltop",
... "1201": "Greenfield",
... "1202": "Sunnydale",
... "1301": "Meadowbrook",
... "1302": "Creekwood"
... }
>>> {code: town for code, town in codes.items() if "1100" <= code <= "1300"}
{
'1101': 'Riverside',
'1102': 'Hilltop',
'1201': 'Greenfield',
'1202': 'Sunnydale'
}
In this example, the condition checks whether the current postal code is between 1100 and 1300. This condition filters the original dictionary, generating a new one with the towns in the target range of codes.
Deciding When to Use Dictionary Comprehensions
When deciding whether to use a dictionary comprehension instead of regular loops or a combination of function calls, you should consider the following factors:
- Conciseness: Dictionary comprehensions reduce the amount of code compared to equivalent
for
loops. - Readability: Dictionary comprehensions can make your code more explicit and readable.
In practice, you can use dictionary comprehensions when you need to do some of the following operations:
- Create a dictionary from an existing iterable
- Merge iterables into a dictionary while transforming keys, values, or both
- Transform dictionary keys, values, or both
- Filter an existing dictionary
So far, you’ve learned how to do all these operations using dictionary comprehensions. Still, you may find other good use cases for dictionary comprehensions during your Python coding experience.
Finally, there are situations when you want to avoid dictionary comprehensions. For example, when you want to process a large dataset to produce key-value pairs. Using dictionary comprehension in this situation will create a large dictionary and store it in memory, which will result in high memory consumption.
To make your code memory-efficient, you may use a generator expression that yields tuples of the form (key, value)
instead:
>>> squares_generator = ((x, x * x) for x in range(1_000_000))
>>> squares_generator
<generator object <genexpr> at 0x106e2ac20>
>>> next(squares_generator)
(0, 0)
>>> next(squares_generator)
(1, 1)
>>> next(squares_generator)
(2, 4)
>>> next(squares_generator)
(3, 9)
In this example, you use a generator expression to build an iterator that yields tuples of two values. The first value is a number, and the second is its square value.
Note: You don’t get direct look-up with a generator. If you rely on looking up the values by their key, then a generator expression is a clumsy replacement for a dictionary comprehension.
The resulting iterator yields tuples on demand, meaning that you’ll only use memory to store one tuple at a time. You don’t need to store a dictionary of a million key-value pairs in your computer’s memory, and avoiding this will make your code more efficient.
Instead, you can use the built-in next()
function to traverse the resulting iterator, or you can use a for
loop.
Exploring Common Bad Practices
You should avoid a few bad practices when working with dictionary comprehensions in your Python code. Some of the most common include the following:
- Using complex expressions in comprehensions
- Writing nested comprehensions with several
for
clauses or several conditionals - Running costly transformations while building the keys and values
- Trying to access comprehension variables from the outside
Sometimes, you may end up with a dictionary comprehension where the comprehension expression is too complicated. For example, you may want to apply transformations conditionally and think of something like the following:
>>> fruits = {"apple": 1.0, "banana": 0.5, "cherry": 2.0, "mango": 2.3}
>>> with_discount = ["apple", "cherry"]
>>> {
... fruit: price * 0.9 if fruit in with_discount else price
... for fruit, price in fruits.items()
... }
{'apple': 0.9, 'banana': 0.5, 'cherry': 1.8, 'mango': 2.3}
In this comprehension, you apply a price discount to a list of selected fruits. To do this, you use a conditional expression as the comprehension expression. You may find it challenging to read this comprehension and decipher what it does. When a complicated expression makes your code difficult to read, you may benefit from using a regular for
loop instead to make your code more readable.
Nested comprehensions with several for
clauses or conditionals can make your code less readable. So, in general, you should avoid them and use more readable constructs like a regular loop.
Trying to use the variables that you define in a comprehension outside of the comprehension itself isn’t possible:
>>> {value: value**3 for value in range(1, 11)}
{
1: 1,
2: 8,
3: 27,
4: 64,
5: 125,
6: 216,
7: 343,
8: 512,
9: 729,
10: 1000
}
>>> value
Traceback (most recent call last):
...
NameError: name 'value' is not defined
The value
variable is only visible within the comprehension. If you try to use it outside the comprehension, then you get a NameError
.
Sometimes, when working with dictionary comprehensions, you may need to run costly data transformations to generate keys, values, or both. In those situations, you need to be aware that building the final dictionary in memory may take considerable time. A possible workaround is to use a generator that produces the key-value pairs on demand.
Conclusion
You’ve learned about Python dictionary comprehensions in detail. They’re a powerful tool for creating, transforming, and filtering dictionaries using concise and clean syntax. You’ve also learned about some bad practices and pitfalls that you should avoid when working with dictionary comprehensions.
Dictionary comprehensions are an excellent resource for Python developers, providing a Pythonic and streamlined way to manipulate dictionaries, which are fundamental data structures in Python.
In this tutorial, you’ve:
- Created new dictionaries with a concise syntax
- Transformed existing dictionaries with comprehensions
- Filtered unwanted key-value pairs from dictionaries
- Decided when to use comprehensions in your code
With these skills, you can write more readable and Pythonic code to process dictionaries. As you continue to use dictionary comprehensions, you’ll find them to be an invaluable tool.
Get Your Code: Click here to download the free sample code that you’ll use to learn about dictionary comprehensions in Python.
Take the Quiz: Test your knowledge with our interactive “Python Dictionary Comprehensions: How and When to Use Them” quiz. You’ll receive a score upon completion to help you track your learning progress:
Interactive Quiz
Python Dictionary Comprehensions: How and When to Use ThemIn this quiz, you'll test your understanding of Python dictionary comprehensions. Dictionary comprehensions are a concise and quick way to create, transform, and filter dictionaries in Python, and can significantly enhance your code's conciseness and readability.