Phase 2 · Data StructuresModule 12~30 min read

Comprehensions & Generator Expressions

Write concise, expressive transformations with list, dict, and set comprehensions.

What you'll learn

Comprehensions are one of Python's most beloved features — a concise, readable way to build a list, dict, or set from another collection in a single line. Master them and your code becomes shorter and clearer. Their lazy cousin, the generator expression, handles huge data with almost no memory.

By the end you'll be able to:

  • Replace many loops with a clean list comprehension
  • Filter and transform inside a comprehension
  • Build dictionaries and sets the same way
  • Use generator expressions for memory-efficient, lazy sequences

List comprehensions

A huge amount of code is just "make a new list by doing something to each item of an old one." A list comprehension expresses exactly that, in one line — no append, no temporary list:

comprehension.py
# the long way
squares = []
for n in range(1, 6):
    squares.append(n * n)

# the comprehension way — one readable line
squares = [n * n for n in range(1, 6)]
print(squares)
Anatomy of a comprehension
[n * n for n in range(5) if n > 0]

The expression

What to put in the new list, for each item.

The loop

Where the items come from.

The condition (optional)

Keep only items that match.

Note

Read it left to right: "n squared, for each n in the range, where n is positive." That reading order is the key to writing them fluently.

Filtering & if-else

Comprehensions can do two different jobs with if, and the position matters. An if at the end filters (keeps some items). An if/else at the start (before the for) transforms every item:

filtering.py
nums = range(1, 11)

# FILTER: an 'if' at the end keeps only matching items
evens = [n for n in nums if n % 2 == 0]
print(evens)   # [2, 4, 6, 8, 10]

# TRANSFORM: if/else goes BEFORE the 'for'
labels = ["even" if n % 2 == 0 else "odd" for n in range(1, 5)]
print(labels)

Dict & set comprehensions

The same idea works for dictionaries and sets — just swap the brackets. Use curly braces with key: value for a dict comprehension, or a single value for a set comprehension:

dict_set.py
words = ["apple", "banana", "cherry"]

# dict comprehension: {key: value for ...}
lengths = {w: len(w) for w in words}
print(lengths)

# set comprehension: {value for ...}
first_letters = {w[0] for w in words}
print(sorted(first_letters))

Generator expressions

Change the square brackets to parentheses and you get a generator expression. Instead of building the whole collection at once, it produces values lazily — one at a time, on demand. For large or infinite data, that's the difference between using kilobytes and gigabytes:

Eager list vs lazy generator

[ ... ] — list comprehension

Eager. Builds the whole list in memory right away. Use it when you need the list.

( ... ) — generator expression

Lazy. Produces values one at a time, using tiny memory. Use it for large data or when you only iterate once.

generator.py
# a list comprehension builds the ENTIRE list in memory
squares_list = [n * n for n in range(1_000_000)]   # lots of memory

# a generator expression is LAZY — values on demand, tiny memory
squares_gen = (n * n for n in range(1_000_000))    # note the ( )

# perfect for feeding an aggregate without building a list
print(sum(n * n for n in range(1, 6)))   # 55

Tip

When you pass a generator straight into a function like sum(), max(), or any(), you can even drop the parentheses — sum(n * n for n in nums). You'll go much deeper on generators (with yield) in Module 22.

Recap & quick check

Key takeaways

  • A list comprehension [expr for item in iterable] builds a new list in one readable line.
  • An 'if' at the end filters; an 'if/else' before the 'for' transforms every item.
  • Dict {k: v for ...} and set {v for ...} comprehensions work the same way with curly braces.
  • A generator expression uses ( ) instead of [ ] and is lazy — tiny memory, values on demand.
  • Use comprehensions for readability, and generators for large data or one-time iteration.

Quick check

1. What does [n * 2 for n in range(3)] produce?

2. Where does a filtering 'if' go in a comprehension?

3. How do you write a dict comprehension?

4. What's the difference between [ ] and ( ) comprehensions?

5. Why use a generator expression for large data?

Excellent — you've completed Phase 2! You command Python's core data structures and can transform them elegantly. Next comes Phase 3 — Object-Oriented Python, where you'll design your own types.