Python Dictionary Comprehensions: How and When to Use Them

Python Dictionary Comprehensions: How and When to Use Them

by Leodanis Pozo Ramos Nov 13, 2024 intermediate python

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.

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 Them

In 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:

Python Syntax
{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:

Python
>>> 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.

You can also create new dictionaries using the dict() constructor:

Python
>>> 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:

Python
>>> 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:

Python Syntax
{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:

  1. Enclosing brackets: Curly braces ({}) are used for dictionary comprehensions.
  2. 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.
  3. The current member: This is the current item or value in the iterable.
  4. 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:

Python
>>> 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:

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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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.

You can get the same result using the following code that combines dict() and zip() with the .values() and .keys() dictionary methods:

Python
>>> 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.

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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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:

Python
>>> 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.

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:

Python
>>> 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:

Python
>>> {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.

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 Them

In 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.

🐍 Python Tricks 💌

Get a short & sweet Python Trick delivered to your inbox every couple of days. No spam ever. Unsubscribe any time. Curated by the Real Python team.

Python Tricks Dictionary Merge

About Leodanis Pozo Ramos

Leodanis is an industrial engineer who loves Python and software development. He's a self-taught Python developer with 6+ years of experience. He's an avid technical writer with a growing number of articles published on Real Python and other sites.

» More about Leodanis

Each tutorial at Real Python is created by a team of developers so that it meets our high quality standards. The team members who worked on this tutorial are:

Master Real-World Python Skills With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

Master Real-World Python Skills
With Unlimited Access to Real Python

Locked learning resources

Join us and get access to thousands of tutorials, hands-on video courses, and a community of expert Pythonistas:

Level Up Your Python Skills »

What Do You Think?

Rate this article:

What’s your #1 takeaway or favorite thing you learned? How are you going to put your newfound skills to use? Leave a comment below and let us know.

Commenting Tips: The most useful comments are those written with the goal of learning from or helping out other students. Get tips for asking good questions and get answers to common questions in our support portal.


Looking for a real-time conversation? Visit the Real Python Community Chat or join the next “Office Hours” Live Q&A Session. Happy Pythoning!