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 filtering if goes at the end; a choosing if/else goes at the start, before for.

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 plain for loop.
  • 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

TypeSyntaxProduces
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.