The Basic Pattern
Every list comprehension follows this structure:
[expression for item in iterable]
Instead of writing:
squares = []
for x in range(10):
squares.append(x ** 2)
You write:
squares = [x ** 2 for x in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Same result. One line. Clear intent.
Adding Conditions
Filter elements with an if clause:
even_squares = [x ** 2 for x in range(10) if x % 2 == 0]
# [0, 4, 16, 36, 64]
If-Else in Comprehensions
To choose between two expressions, put the conditional before the for:
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
# ["even", "odd", "even", "odd", "even"]
Nested Comprehensions
Flatten a list of lists:
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in matrix for num in row]
# [1, 2, 3, 4, 5, 6]
Read nested comprehensions left to right, matching the order of equivalent nested for loops.
When Not to Use Them
List comprehensions are great for simple transformations. If your logic requires multiple conditions, nested loops, or side effects, use a regular for loop instead. Readability always wins.
# Too complex - use a regular loop instead
result = [
transform(x)
for x in data
if condition_one(x)
if condition_two(x)
for y in x.children
if y.is_valid()
]