Comprehensions are Python's way of creating collections concisely. Here's how to use them well.

Basic List Comprehension

# Traditional loop
squares = []
for x in range(10):
    squares.append(x ** 2)
 
# List comprehension
squares = [x ** 2 for x in range(10)]

Same result, one line.

The Pattern

[expression for item in iterable]

Read it as: "give me expression for each item in iterable"

With Conditions

# Only even numbers
evens = [x for x in range(20) if x % 2 == 0]
 
# With else (different syntax)
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
# ['even', 'odd', 'even', 'odd', 'even']

Note: if at the end filters. if/else in the expression transforms.

Transforming Data

names = ["alice", "bob", "charlie"]
 
# Capitalize
upper_names = [name.upper() for name in names]
 
# Get lengths
lengths = [len(name) for name in names]
 
# Extract field
users = [{"name": "Alice"}, {"name": "Bob"}]
names = [user["name"] for user in users]

Nested Loops

# Traditional
pairs = []
for x in range(3):
    for y in range(3):
        pairs.append((x, y))
 
# Comprehension
pairs = [(x, y) for x in range(3) for y in range(3)]
# [(0, 0), (0, 1), (0, 2), (1, 0), ...]

Read left to right, outer loop first.

Flattening Lists

nested = [[1, 2], [3, 4], [5, 6]]
 
# Flatten
flat = [x for sublist in nested for x in sublist]
# [1, 2, 3, 4, 5, 6]

Dictionary Comprehensions

# Create dict from two lists
keys = ["a", "b", "c"]
values = [1, 2, 3]
d = {k: v for k, v in zip(keys, values)}
# {'a': 1, 'b': 2, 'c': 3}
 
# Transform dict
prices = {"apple": 1.0, "banana": 0.5}
doubled = {k: v * 2 for k, v in prices.items()}
 
# Filter dict
expensive = {k: v for k, v in prices.items() if v > 0.75}
 
# Swap keys and values
inverted = {v: k for k, v in prices.items()}

Set Comprehensions

# Unique values
numbers = [1, 2, 2, 3, 3, 3, 4]
unique = {x for x in numbers}
# {1, 2, 3, 4}
 
# Unique transformations
words = ["hello", "world", "hello"]
unique_upper = {w.upper() for w in words}
# {'HELLO', 'WORLD'}

Generator Expressions

Like list comprehensions, but lazy:

# List - creates all values immediately
squares = [x ** 2 for x in range(1000000)]
 
# Generator - creates values on demand
squares = (x ** 2 for x in range(1000000))

Use generators for large datasets to save memory.

When to Use Comprehensions

Good uses:

# Simple transformations
upper = [s.upper() for s in strings]
 
# Simple filtering
positive = [x for x in numbers if x > 0]
 
# Creating dicts/sets
lookup = {item.id: item for item in items}

Avoid when:

# Too complex - use a loop
result = [
    transform(x) 
    for x in items 
    if condition1(x) 
    if condition2(x)
    for y in x.children
    if another_condition(y)
]
 
# Side effects - use a loop
# Bad: comprehension for side effects
[print(x) for x in items]  # Don't do this
 
# Good: explicit loop
for x in items:
    print(x)

Readability Guidelines

One line if simple:

squares = [x ** 2 for x in range(10)]

Multi-line if needed:

result = [
    transform(item)
    for item in items
    if item.active
]

Use a loop if complex:

# If you need multiple statements per item
# If the comprehension would be confusing
# If you have side effects

Common Patterns

# Enumerate in comprehension
indexed = [(i, x) for i, x in enumerate(items)]
 
# Zip in comprehension
pairs = [(a, b) for a, b in zip(list1, list2)]
 
# With function calls
processed = [process(x) for x in items if validate(x)]
 
# Conditional transformation
result = [x if x > 0 else 0 for x in numbers]
 
# Multiple conditions
filtered = [x for x in items if x > 0 if x < 100]
# Same as: if x > 0 and x < 100

Performance

Comprehensions are typically faster than loops:

# Slower
result = []
for x in range(1000):
    result.append(x ** 2)
 
# Faster
result = [x ** 2 for x in range(1000)]

The comprehension avoids repeated append method lookups.

My Rules

  1. Use for simple transforms and filters
  2. Keep them short - if it wraps more than twice, use a loop
  3. No side effects - comprehensions are for creating values
  4. Choose clarity over cleverness

When in doubt, use a loop. Clear code beats clever code.

React to this post: