Comprehensions are one of Python's most loved features: a compact, readable way to build a list, dictionary, or set from an existing iterable in a single line. They replace multi-line for-loop-and-append patterns with expressive one-liners that are usually faster too.
This guide covers all four comprehension types end-to-end — list, dictionary, set, and generator — with filtering conditions, transformations, nested loops, and the all-important question of when not to use them. Every example is runnable with its output.
List Comprehension Basics
The pattern is [expression for item in iterable]. Compare the classic loop with the comprehension — same result, far less code.
# Classic way
squares = []
for x in range(6):
squares.append(x * x)
# Comprehension way
squares = [x * x for x in range(6)]
print(squares)
Output:
[0, 1, 4, 9, 16, 25]
Adding a Condition (Filtering)
Add an if at the end to keep only items that match: [expr for item in iterable if condition].
nums = range(10)
evens = [n for n in nums if n % 2 == 0]
print(evens)
Output:
[0, 2, 4, 6, 8]
if/else Inside a Comprehension
To choose between two values (rather than filter), put the conditional expression before the for: [a if cond else b for item in iterable].
nums = range(6)
labels = ["even" if n % 2 == 0 else "odd" for n in nums]
print(labels)
Output:
['even', 'odd', 'even', 'odd', 'even', 'odd']
Remember the position rule: a filteringifgoes at the end; a choosingif/elsegoes at the start, beforefor.
Nested Loops in a Comprehension
Multiple for clauses run left-to-right, like nested loops. Great for flattening or building pairs.
# Flatten a 2D list
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [num for row in matrix for num in row]
print(flat)
# All coordinate pairs
pairs = [(x, y) for x in [1, 2] for y in ["a", "b"]]
print(pairs)
Output:
[1, 2, 3, 4, 5, 6]
[(1, 'a'), (1, 'b'), (2, 'a'), (2, 'b')]
Dictionary Comprehensions
Same idea with {key: value for ...} to build a dict in one line.
# Map numbers to their squares
square_map = {n: n * n for n in range(1, 6)}
print(square_map)
# Swap keys and values
prices = {"apple": 3, "banana": 1}
inverted = {v: k for k, v in prices.items()}
print(inverted)
Output:
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
{3: 'apple', 1: 'banana'}
Set Comprehensions
Use {expr for ...} (curly braces, no key:value) to build a set — automatically removing duplicates.
words = ["hi", "HI", "Hey", "hey", "hi"]
unique_lower = {w.lower() for w in words}
print(unique_lower)
Output:
{'hi', 'hey'}
Generator Expressions (the Lazy Cousin)
Swap the brackets for parentheses and you get a generator — values are produced lazily, ideal when you only iterate once or the data is huge.
# Sum of squares without building a list in memory
total = sum(x * x for x in range(1_000_000))
print(total)
Output:
333332833333500000
Real-World Example: Cleaning and Transforming Data
A common task: take raw input, strip whitespace, drop blanks, normalize case, and index it — all with comprehensions.
raw = [" Alice ", "", "BOB", " ", "charlie"]
# Clean: strip, drop empties, title-case
names = [name.strip().title() for name in raw if name.strip()]
print(names)
# Build a lookup of name -> length
lengths = {name: len(name) for name in names}
print(lengths)
Output:
['Alice', 'Bob', 'Charlie']
{'Alice': 5, 'Bob': 3, 'Charlie': 7}
When NOT to Use a Comprehension
Comprehensions shine for simple transforms and filters. Reach for a regular loop when logic gets complex.
- Side effects only — don't write
[print(x) for x in items]; use a plainforloop. - Deeply nested / many conditions — if it no longer fits comfortably on one readable line, a loop is clearer.
- Try/except needed — comprehensions can't catch exceptions; use a loop.
- Huge data you iterate once — use a generator expression, not a list comprehension, to save memory.
Summary Table
| Type | Syntax | Produces |
|---|---|---|
| List | [x for x in it] | A list |
| With filter | [x for x in it if cond] | A filtered list |
| With if/else | [a if c else b for x in it] | A transformed list |
| Dictionary | {k: v for ... } | A dict |
| Set | {x for x in it} | A set (unique) |
| Generator | (x for x in it) | A lazy generator |
Conclusion
Comprehensions let you express βbuild a collection from this iterableβ directly and readably. Learn the four flavours and the if-position rule, and you'll write cleaner Python that often runs faster than the equivalent loop — while knowing when a plain loop is the more honest choice.
Try converting your next three for-append loops into list comprehensions. Then, whenever you only loop over the result once, switch the brackets to parentheses for a free memory win.
π¬ Comments (0)
No comments yet. Be the first to share your thoughts!