Back to Blog
Python

Python Dict Comprehension Syntax: A Practical Guide

python dict comprehension syntax: Learn Python dict comprehension syntax with practical examples, conditionals, nested comprehensions, and performance considerations.

dict comprehensionPython dictionariesdata transformationPython syntaxcode readability
Illustration of Python dict comprehension syntax showing key-value mapping from an iterable.

Python dict comprehension syntax lets you build dictionaries from iterables in a single expression. It follows the same pattern as list comprehensions but produces a mapping instead of a sequence. For example, {x: x**2 for x in range(5)} creates {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}. This compact form is useful when you need to transform one collection into a dictionary without writing an explicit loop and accumulating values manually.

The Basic Syntax

The core syntax is straightforward:

{key_expression: value_expression for item in iterable}

The key_expression and value_expression are evaluated for each item in the iterable. Both can reference the loop variable item, or any other variable in scope. Here is a minimal example that maps strings to their lengths:

words = ["apple", "banana", "cherry"] lengths = {word: len(word) for word in words} # {'apple': 5, 'banana': 6, 'cherry': 6}

This replaces the more verbose loop:

lengths = {} for word in words: lengths[word] = len(word)

The comprehension version is more readable because the intent is declared directly: a dictionary where each key is a word and each value is its length.

Adding Conditions with if and else

You can filter items with an if clause at the end of the comprehension. This excludes items that do not satisfy the condition:

even_squares = {x: x**2 for x in range(10) if x % 2 == 0} # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

The if clause only controls which items are included; it does not change the key or value expressions. If you need to produce different values based on a condition, use a conditional expression in the value (or key) position:

parity = {x: "even" if x % 2 == 0 else "odd" for x in range(5)} # {0: 'even', 1: 'odd', 2: 'even', 3: 'odd', 4: 'even'}

This is equivalent to writing an if-else inside the loop body. The comprehension allows only one if filter at the end, but you can combine it with a conditional expression for the key or value.

Nested Dict Comprehensions

Dict comprehensions can use multiple for clauses to iterate over nested structures. This is useful for building dictionaries of dictionaries. For example, to create a multiplication table as a nested dict:

table = {i: {j: i * j for j in range(1, 6)} for i in range(1, 6)}

The outer comprehension iterates over i, and for each i, the inner comprehension builds a dictionary mapping j to i * j. The result is a 5x5 table. Nested comprehensions can become hard to read if they go deeper than two levels. In such cases, a regular loop with explicit variable names is often clearer.

Using enumerate, zip, and Other Iterables

Dict comprehensions work with any iterable, including those produced by built-in functions. A common pattern is to build a dictionary from an enumerated list, using the index as the key:

colors = ["red", "green", "blue"] color_map = {i: color for i, color in enumerate(colors)} # {0: 'red', 1: 'green', 2: 'blue'}

Similarly, zip lets you combine two sequences into key-value pairs:

keys = ["name", "age", "city"] values = ["Alice", 30, "New York"] person = {k: v for k, v in zip(keys, values)} # {'name': 'Alice', 'age': 30, 'city': 'New York'}

You can also use dictionary methods like .items() on an existing dict to transform it:

original = {"a": 1, "b": 2} inverted = {v: k for k, v in original.items()} # {1: 'a', 2: 'b'}

This is a concise way to swap keys and values, but be aware that if the original values are not unique, later keys will overwrite earlier ones.

Performance and Memory Considerations

Dict comprehensions are not inherently faster than an explicit loop. They are a syntactic convenience that often improves readability, but the runtime behavior is similar: the same number of iterations and assignments occur. The main performance difference comes from avoiding repeated method calls like dict[key] = value in a loop, but Python's bytecode for a comprehension is optimized slightly. For large iterables, the comprehension builds the entire dictionary in memory at once, just like a loop would. If you need to build a dictionary incrementally or conditionally over a very large stream, a generator expression with dict() might be more memory-efficient:

dict((x, x**2) for x in range(1000000))

This passes a generator to dict, which consumes items lazily. However, the resulting dictionary still holds all key-value pairs, so the memory footprint is the same. The real tradeoff is between readability and the need for early termination or side effects. If you need to break out of the loop based on a complex condition, a regular for loop is more flexible.

Common Mistakes and How to Avoid Them

One frequent mistake is assuming that the if clause can be placed before the for clause. The correct order is {key: value for item in iterable if condition}. Putting if earlier results in a syntax error.

Another issue is key collisions. If the key expression produces duplicate keys, the last value wins silently. This can hide bugs when transforming data with non-unique keys. For example:

data = [("a", 1), ("a", 2)] result = {k: v for k, v in data} # {'a': 2}

If you expect to keep all values, you need to aggregate them manually or use a defaultdict.

Finally, avoid using mutable default values as keys or values in a comprehension. Since the expressions are evaluated fresh for each iteration, this is less risky than in function definitions, but it can still lead to unintended shared state if you reuse a mutable object like a list or dict as a value.

When to Use Regular Loops Instead

Dict comprehensions are best for simple transformations that fit on one line and do not require complex control flow. Use a regular loop when you need to:

  • Update an existing dictionary in place.
  • Perform multiple operations per item that are not easily expressed in a single expression.
  • Break out of the loop early based on a condition.
  • Log or debug each iteration.
  • Build a dictionary incrementally over a long-running process.

A regular loop also makes it easier to add comments or handle exceptions per item. For example, if a value conversion might raise an exception and you need to skip that item, a comprehension cannot catch the exception without a helper function. In that case, a loop with try-except is clearer.

result = {} for key, value in raw_data: try: result[key] = int(value) except ValueError: continue

This is more maintainable than trying to force the same logic into a comprehension. The dict comprehension syntax is a powerful tool, but it is not always the right one. Choose it when the mapping is straightforward and the comprehension reads naturally; choose a loop when the logic needs more room to express itself.

python dict comprehension syntax: Practical Usage and Code E | RYUSLOG DEV