Lesson 11 of 34 · 0 of 2 exercises solved

Comprehensions & Generators

build a new , dict or from an existing one in a single line. Use them for simple transformations and switch to a regular when the logic gets complicated.

# List comprehension — [expression for item in iterable if condition]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

squares = [n**2 for n in numbers]
print(squares)  # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

evens = [n for n in numbers if n % 2 == 0]
print(evens)  # [2, 4, 6, 8, 10]

even_squares = [n**2 for n in numbers if n % 2 == 0]
print(even_squares)  # [4, 16, 36, 64, 100]

# Nested comprehension (flatten a 2D list)
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)  # [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Dict comprehension
words = ["hello", "world", "python"]
lengths = {word: len(word) for word in words}
print(lengths)  # {'hello': 5, 'world': 5, 'python': 6}

# Set comprehension
dupes = [1, 2, 2, 3, 3, 3, 4]
unique = {x**2 for x in dupes}
print(unique)  # {1, 4, 9, 16} (order not guaranteed)

# Conditional expression (ternary)
labels = ["even" if n % 2 == 0 else "odd" for n in range(1, 6)]
print(labels)  # ['odd', 'even', 'odd', 'even', 'odd']
Python (loads on first run)Ctrl+Enter runs
# Generator expressions — lazy, memory-efficient
# Use () instead of []
gen = (n**2 for n in range(1_000_000))  # creates no list yet
print(next(gen))  # 0
print(next(gen))  # 1
print(sum(gen))   # computes on the fly

# Generator function — yield instead of return
def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fib = fibonacci()
print([next(fib) for _ in range(10)])  # [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

# Generator with yield from
def chain(*iterables):
    for it in iterables:
        yield from it

print(list(chain([1, 2], [3, 4], [5])))  # [1, 2, 3, 4, 5]

# itertools — powerful combinator utilities
import itertools

print(list(itertools.islice(fibonacci(), 8)))     # first 8 Fibonacci numbers
print(list(itertools.product([0,1], repeat=3)))   # all 3-bit binary combos
print(list(itertools.combinations("ABCD", 2)))    # C(4,2) = 6 pairs
pairs = list(itertools.zip_longest([1,2,3], [4,5], fillvalue=0))
print(pairs)  # [(1, 4), (2, 5), (3, 0)]
Python (loads on first run)Ctrl+Enter runs

Common question

Is a comprehension just a shorter loop?

A comprehension is an expression that builds a collection from an by mapping and filtering: [f(x) for x in xs if p(x)]. Because it is an expression, you can assign it, return it or pass it directly, and it tells the reader this is a pure transformation with no side effects. Dict and set comprehensions build those types; a generator expression gives the same values lazily.

Use comprehensions for transformations that fit on one readable line. Use loops when there are side effects, several outputs, or logic that deserves a name. Prefer a generator expression when the result is used once by sum, max, any, all or a join.

Source: The Zen of Python: "Beautiful is better than ugly. Simple is better than complex."

Common mix-ups

Each of these sounds reasonable. Think about why it is wrong, then open the explanation.

  • A comprehension does the same work as a loop with append, so it's only a matter of taste.

  • If one comprehension is good, nesting three of them is better.

  • A generator expression is just a list comprehension with round brackets.

Practice

Rewrite the loop as a single list comprehension that collects the squares of the odd numbers from 1 to 20.

Exercise

Squares of odds

2 checks
squares = []
for n in range(1, 21):
    if n % 2 == 1:
        squares.append(n * n)

print(squares)
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Build two things with comprehensions: lengths, a dict mapping each word to its length, and flat, a single flat list of every number in the nested matrix.

Exercise

Dict and nested comprehensions

3 checks
words = ["python", "is", "wonderful"]
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

lengths = {}
flat = []

print(lengths)
print(flat)
 
Python (loads on first run)Ctrl+Enter runs
Output
Press Run to try your code, then Check answer to grade it.

Check yourself

Quick check

What is the difference between [x * 2 for x in data] and (x * 2 for x in data)?

Finished reading?2 exercises still open. You can come back to them later.

Tip: use the ← and → keys to move between lessons.