The Basics
A list comprehension creates a new list by transforming or filtering an existing iterable:
# Basic syntax: [expression for item in iterable]
squares = [x**2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# With filter: [expression for item in iterable if condition]
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]
Equivalent for loop:
even_squares = []
for x in range(10):
if x % 2 == 0:
even_squares.append(x**2)
The comprehension version is:
- More concise
- Generally faster (CPython optimizes them)
- More readable once you're comfortable with the syntax
String Operations
List comprehensions work on strings and with any expression:
# Process a list of strings
words = [' hello ', ' world ', ' python ']
cleaned = [w.strip().capitalize() for w in words]
# ['Hello', 'World', 'Python']
# Filter by string property
files = ['main.py', 'utils.py', 'README.md', 'test.py', '.gitignore']
python_files = [f for f in files if f.endswith('.py')]
# ['main.py', 'utils.py', 'test.py']
# Transform file extensions
names = [f.replace('.py', '') for f in python_files]
# ['main', 'utils', 'test']
Nested Comprehensions
Flatten a list of lists:
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [n for row in matrix for n in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Read left to right: "for each row in matrix, for each n in that row."
Nested comprehension (creates a 2D structure):
# Transpose a matrix
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Dict and Set Comprehensions
The same syntax works for dicts and sets:
# Dict comprehension: {key: value for item in iterable}
squares_dict = {x: x**2 for x in range(6)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Invert a dictionary
original = {'a': 1, 'b': 2, 'c': 3}
inverted = {v: k for k, v in original.items()}
# {1: 'a', 2: 'b', 3: 'c'}
# Set comprehension: no duplicates
words = ['apple', 'banana', 'apple', 'cherry', 'banana']
unique = {w[0] for w in words} # first letters, unique
# {'a', 'b', 'c'}
Generator Expressions
If you don't need the whole list at once, use a generator expression (same syntax with () instead of []):
# List: builds entire list in memory
sum_squares_list = sum([x**2 for x in range(1_000_000)])
# Generator: processes one item at a time, uses minimal memory
sum_squares_gen = sum(x**2 for x in range(1_000_000))
# They produce the same result, but the generator is much more memory-efficient
Use generators when:
- The result is consumed once (e.g., passed to
sum(),max(),any(),all()) - The iterable is very large
- You're chaining multiple operations
Conditional Expressions (Ternary in Comprehensions)
# if-else in the expression part (not the filter part)
numbers = [1, -3, 5, -7, 9, -2]
absolute = [x if x >= 0 else -x for x in numbers]
# [1, 3, 5, 7, 9, 2]
# Same as abs() — but demonstrates the pattern
labeled = ['positive' if x > 0 else 'negative' if x < 0 else 'zero'
for x in numbers]
# ['positive', 'negative', 'positive', 'negative', 'positive', 'negative']
When NOT to Use Comprehensions
Comprehensions aren't always the answer:
# ❌ Too complex — use a regular loop
result = [
transform(item)
for category in categories
for item in category.items
if item.active and item.value > threshold
if item.category != excluded_category
]
# ✅ More readable as a loop
result = []
for category in categories:
for item in category.items:
if item.active and item.value > threshold and item.category != excluded_category:
result.append(transform(item))
# ❌ Side effects in a comprehension — use a loop
[print(x) for x in items] # Don't do this
# ✅ For side effects, use a loop
for x in items:
print(x)
Rule: If the comprehension is hard to read at a glance, refactor it to a loop.
Key Takeaways
- List comprehensions:
[expression for item in iterable if condition] - Dict comprehensions:
{key: value for item in iterable} - Set comprehensions:
{expression for item in iterable} - Generator expressions:
(expression for item in iterable)— memory-efficient for large data - For complex logic or side effects: use regular loops
- The
if-elsein the expression (ternary) is different from the filterifat the end