Lesson 7: Comprehensions — Clean, Fast Loops
Build lists, dicts, and sets in one elegant line with comprehensions and generator expressions.
The Most Pythonic Loop
A list comprehension builds a new list in a single expression. It is shorter, faster, and easier to read than a manual for loop that appends. Once you learn to read them, comprehensions become the tool you reach for first.
Comprehensions are one of the defining features of Python — many other languages have copied them since. They appear on virtually every interview question, in every codebase, and in every data-processing script. This lesson makes you fluent in reading and writing them.
What You'll Learn in This Lesson
- Read and write list comprehensions with filters
- Build dict and set comprehensions
- Use generator expressions for memory-friendly data
- Know when NOT to use a comprehension
Anatomy of a Comprehension
[expression for item in sequence if condition]
| Part | Meaning |
|---|---|
expression |
What each output item looks like |
for item in sequence |
The loop |
if condition |
Optional filter — item skipped when False |
Example — squares of all numbers:
numbers = [1, 2, 3, 4]
squares = [n ** 2 for n in numbers] # [1, 4, 9, 16]
evens = [n for n in numbers if n % 2 == 0] # [2, 4]
Read it right-to-left: first the loop ("for each n in numbers"), then the filter ("if ..."), then the expression ("produce n ** 2"). Visualize a factory line: items enter on the conveyor belt, get checked at the gate, and come out transformed.
Comprehension vs Manual Loop
| Manual loop | Comprehension |
|---|---|
result = [] |
result = [n ** 2 for n in numbers] |
for n in numbers: |
— |
result.append(n ** 2) |
— |
The comprehension is one line, runs faster (C-level loop under the hood), and cannot accidentally forget the append. Measurable speed differences appear on big lists.
Why is it faster? Python optimizes comprehensions at the interpreter level — the loop runs in C rather than going through Python's slower per-instruction machinery. For a million items, comprehensions are typically 1.5–2× faster than manual append loops.
Dict and Set Comprehensions
The same idea works for dictionaries and sets — just change the brackets:
| Kind | Syntax | Example |
|---|---|---|
| List | [expr for item in seq] |
[n for n in range(5)] |
| Set | {expr for item in seq} |
{n % 3 for n in range(9)} |
| Dict | {key: value for item in seq} |
{n: n ** 2 for n in range(3)} |
cubes = {n: n ** 3 for n in numbers if n % 2 == 1}
letters = {ch.lower() for ch in "Abracadabra"} # unique letters
Dict comprehensions are everywhere in data work — converting lists of records into lookup tables:
users = [{"id": 1, "name": "Amol"}, {"id": 2, "name": "Riya"}]
by_id = {u["id"]: u["name"] for u in users}
print(by_id[2]) # Riya
Generator Expressions — Lazy & Memory-Friendly
Replace the square brackets with parentheses and you get a generator expression:
gen = (n * 10 for n in range(5))
print(list(gen)) # [0, 10, 20, 30, 40]
- A list comprehension builds the whole list in memory.
- A generator produces one item at a time — perfect for huge data.
- Use generators directly in
sum(),max(),any(),min()to avoid intermediate lists:
total = sum(n * n for n in range(1_000_000)) # no giant list created
Mental model: a list comprehension is a completed warehouse shelf; a generator is a live conveyor belt that hands you one item at a time. The belt uses almost no storage.
When NOT to Use a Comprehension
Comprehensions are powerful but not always the answer:
- Logic needs more than one condition → write a normal loop.
- The body spans multiple lines → write a normal loop.
- You only need the side effect (like printing) → a normal loop is clearer.
- Readability always wins. If the comprehension is hard to read, it is too clever.
The readability test: if you cannot understand the comprehension at a glance, split it — either into a loop or into a helper function. Professionals optimize for the next reader, not for the shortest possible line.
Common Mistakes to Avoid
- Mistake: Putting the condition after the expression but with wrong order — Fix: remember:
[expr for item in seq if cond]— theifalways comes after thefor. - Mistake: Using a comprehension for side effects like
print— Fix: use a regular loop; comprehensions are for building collections. - Mistake: A comprehension too long to fit on one line — Fix: switch to a loop. One-liners are only elegant when short.
- Mistake: Forgetting the colon in a dict comprehension (
{n: n**2 ...}) — Fix: dict comprehensions always havekey: valuewith a colon. - Mistake: Using
{}expecting a set — Fix:{}is an empty dict; an empty set isset().
Professional Tips & Tricks
- Comprehensions are faster than manual append loops — measurable on big lists.
- Use a generator expression in sum(), max(), or any() to avoid building intermediate lists.
- Keep comprehensions on one line; if it does not fit, use a regular loop.
- Use
{k: v for ...}to build instant lookup tables from lists of records. - Read comprehensions right-to-left: loop → filter → expression.
Key Takeaways
[expr for item in seq if cond]builds lists in one line.- Same pattern with
{}builds sets and dicts. - Parentheses
( )make a lazy, memory-friendly generator. - Use comprehensions for transformations; use loops for side effects and complex logic.
- Generator expressions in sum/max/any avoid huge intermediate lists.
Next up: Module 3 — data structures. Lists & tuples first.
# Comprehensions in action
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
# Squares of all numbers
squares = [n ** 2 for n in numbers]
print("Squares:", squares)
# Even numbers only
evens = [n for n in numbers if n % 2 == 0]
print("Evens:", evens)
# Dict comprehension: number -> its cube
cubes = {n: n ** 3 for n in numbers if n % 2 == 1}
print("Cubes of odds:", cubes)
# Set comprehension with a string
letters = {ch.lower() for ch in "Abracadabra"}
print("Unique letters:", sorted(letters))
# Generator expression (lazy)
gen = (n * 10 for n in range(5))
print("Generator:", list(gen))Lesson Code (Python)
# Comprehensions in action
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
# Squares of all numbers
squares = [n ** 2 for n in numbers]
print("Squares:", squares)
# Even numbers only
evens = [n for n in numbers if n % 2 == 0]
print("Evens:", evens)
# Dict comprehension: number -> its cube
cubes = {n: n ** 3 for n in numbers if n % 2 == 1}
print("Cubes of odds:", cubes)
# Set comprehension with a string
letters = {ch.lower() for ch in "Abracadabra"}
print("Unique letters:", sorted(letters))
# Generator expression (lazy)
gen = (n * 10 for n in range(5))
print("Generator:", list(gen))Console Output
Squares: [1, 4, 9, 16, 25, 36, 49, 64]
Evens: [2, 4, 6, 8]
Cubes of odds: {1: 1, 3: 27, 5: 125, 7: 343}
Unique letters: ['a', 'b', 'c', 'd', 'r']
Generator: [0, 10, 20, 30, 40]Code Visualization Tips
- Read a comprehension right-to-left: first the loop, then the filter, then the expression.
- Visualize it as a factory line: items enter the conveyor belt (for), get checked (if), and come out transformed (expression).
- Compare a for+append loop with its comprehension in Python Tutor to see identical results with less code.
Professional Tips & Tricks
- Comprehensions are faster than manual append loops — measurable on big lists.
- Use a generator expression in sum(), max(), or any() to avoid building intermediate lists.
- Keep comprehensions on one line; if it does not fit, use a regular loop.
Python Code Judge & Practice Arena
LeetCode StyleRun real Python 3.12 WebAssembly code directly in your browser against automated test suites.
Problem 1: Even Squares Filter 1
Test Your Knowledge
Instant feedbackQuick Check: Lesson 7: List, Dict, & Set Comprehensions
Up next · Continue learning
Lists & Tuples
Mutable lists, immutable tuples, slicing, sorting, and common list methods.