Python Comprehensions

Tutorial 40 of 65 · pythondeck.com Python course

Comprehensions transform iterables into lists, sets, dicts or generators in one expression: [expr for x in src if cond]. They are usually faster and more readable than equivalent loops.

Comprehensions build lists, dicts, sets, and generators from iterables in one expressive line. They are often faster and clearer than manual append loops for simple transforms. The syntax embeds optional if filters and nested for clauses—keep nesting shallow for readability.

Python 3.8+ walrus operator := can assign inside comprehensions sparingly. Dict comprehensions need key: value; set comprehensions use a single expression.

List comprehension: [f(x) for x in items if cond].

Dict comprehension: {k: v for ...}; set comprehension: {expr for ...}.

Generator comprehension: (expr for ...) lazy parentheses form.

Nested comprehensions vs multiple loops (readability trade-off).

When not to use: side effects, multiple branches, very complex logic.

Equivalence to list() of generator expressions for eager lists.

Comprehensions create a new scope for their loop variables in Python 3—the loop name does not leak. For side-effect-free transforms they are idiomatic; for logging or mutation per item, use a regular loop.

Nested comprehensions multiply work—[x*y for x in a for y in b] is O(len(a)*len(b)). Sometimes explicit loops or itertools.product communicate intent better.

Assigning in comprehensions with walrus can obscure code; use only when it genuinely avoids duplicate expensive calls.

Putting side effects (print, append to global lists) inside comprehensions.

Deep nesting that is harder to read than nested for-loops.

Using a list comprehension when you only iterate once (use generator form).

Confusing {x for x in ...} (set) with {x: ...} (dict) syntax.

Building enormous comprehensions that exhaust memory—stream with generators instead.

Prefer comprehensions for simple maps and filters; use loops for complex control flow.

Limit nesting to two levels; extract helper functions for harder cases.

Use generator comprehensions when passing to sum(), any(), or max() once.

Name intermediate logic with functions rather than walrus-heavy one-liners.

Re-read the examples below with these ideas in mind; change variable names and inputs to match your own project.

The program below demonstrates list. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Example: List
# Run in the REPL or save as a .py file and execute with python.
evens = [x for x in range(20) if x % 2 == 0]
print(evens)

This sample walks through dict / set in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Example: Dict / set
# Run in the REPL or save as a .py file and execute with python.
squares = {x: x*x for x in range(6)}
print(squares)
vowels = {c for c in "comprehension" if c in "aeiou"}
print(vowels)

Here is a hands-on illustration of nested. Follow the inline comments first; only then execute the snippet and compare the result with what you expected.

# Example: Nested
# Run in the REPL or save as a .py file and execute with python.
matrix = [[i*j for j in range(4)] for i in range(4)]
for row in matrix:
    print(row)

The program below demonstrates list comp filter. Read the comments on each line, run the code, then change names or values to see how the output shifts.

# Comprehensions build collections in one expression
nums = range(10)  # 0..9
evens = [n for n in nums if n % 2 == 0]  # filter + collect
print(evens)  # [0,2,4,6,8]
squares = {n: n*n for n in nums}  # dict comprehension
print(squares[5])  # 25
unique = {n % 3 for n in nums}  # set comprehension
print(unique)  # remainders
matrix = [[i*j for j in range(3)] for i in range(3)]  # nested
print(matrix[2])  # third row

This sample walks through generator comp in a small, runnable script. Paste it into the REPL or save it as a .py file before you continue to the next block.

# Generator comprehension uses parentheses — lazy
nums = range(1_000_000)  # large range
gen = (n * n for n in nums if n % 2 == 0)  # lazy squares of evens
first = next(gen)  # 0 — first even square
second = next(gen)  # 4 — second
print(first, second)  # 0 4
total = sum(x for x in range(100) if x % 3 == 0)  # divisible by 3
print(total)  # sum of multiples
pairs = [(a, b) for a in (1, 2) for b in (10, 20)]  # nested loops
print(pairs)  # four tuples

« Python Generators All tutorials Python Type Hints »