Lesson 9 / 11

Comprehensions and Generators

Experienced Python code rarely builds a list with a manual loop when it can build one in a single, readable expression instead. This lesson covers the idioms that separate beginner Python from professional Python.

List comprehensions

squares = [n ** 2 for n in range(10)]
even_squares = [n ** 2 for n in range(10) if n % 2 == 0]
names = [student["name"] for student in students]

Read a comprehension the same way you’d read the equivalent loop: “for each n in range(10), keep n ** 2, but only if n % 2 == 0.” It’s the same logic as a for loop with an if and an append() call, just compressed into one line — and once you’re used to reading them, they’re actually faster to understand than the multi-line version.

Dict and set comprehensions

scores = {student["name"]: student["score"] for student in students}
unique_courses = {student["course"] for student in students}

The syntax follows the same pattern as list comprehensions, just with {} instead of [], and a key: value pair for dictionaries instead of a single expression.

Generators — lazy evaluation

def count_up_to(n):
    i = 1
    while i <= n:
        yield i
        i += 1

for number in count_up_to(5):
    print(number)

A generator produces values one at a time, on demand, instead of building the whole list in memory upfront. This becomes essential once you’re processing large files or data streams that wouldn’t fit comfortably in memory as a full list. yield is what turns a normal function into a generator — the function pauses at yield, hands back one value, and resumes exactly where it left off the next time it’s asked for another.

Generator expressions

total = sum(n ** 2 for n in range(1000000))

Drop the square brackets from a list comprehension and you get a generator expression — it computes each value lazily rather than building a million-item list in memory first, which matters a great deal at that scale.

When not to use a comprehension

If the logic inside the loop needs more than one line, or involves multiple conditions that would make the comprehension hard to read in one glance, a regular for loop is the better, more maintainable choice. Comprehensions should make code clearer, not more clever for its own sake.