Python Basics — List Comprehensions
List Comprehensions
List comprehensions provide a concise way to create lists. They are one of Python’s most loved features.
Basic Syntax
[expression for item in iterable]
# Traditional loop
squares = []
for x in range(10):
squares.append(x ** 2)
# List comprehension
squares = [x ** 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
With Conditional Filtering
[expression for item in iterable if condition]
# Even numbers only
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Words longer than 3 characters
words = ["hi", "hello", "hey", "howdy", "go"]
long_words = [w for w in words if len(w) > 3]
print(long_words) # ['hello', 'howdy']
With if-else (Ternary)
When you need else, the expression goes before for:
# Label even/odd
labels = ["even" if x % 2 == 0 else "odd" for x in range(6)]
print(labels) # ['even', 'odd', 'even', 'odd', 'even', 'odd']
Key difference:
- Filter (no else):
[x for x in items if condition]- Transform (if-else):
[a if condition else b for x in items]
Multiple for Clauses (Nested)
# Cartesian product
pairs = [(x, y) for x in range(3) for y in range(3)]
print(pairs)
# [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]
This is equivalent to:
pairs = []
for x in range(3):
for y in range(3):
pairs.append((x, y))
Flattening a 2D List
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
Comprehension vs map() and filter()
numbers = [1, 2, 3, 4, 5]
# Using map + filter
result = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, numbers)))
# Using comprehension (more readable)
result = [x ** 2 for x in numbers if x % 2 == 0]
print(result) # [4, 16]
Comprehensions are generally preferred for readability. Use map()/filter() when the function already exists:
words = ["hello", "WORLD", "Python"]
lower = list(map(str.lower, words)) # cleaner with existing method
# vs
lower = [w.lower() for w in words] # also fine
Performance Notes
List comprehensions are slightly faster than equivalent for loops because the loop runs at C speed internally:
import timeit
# Loop approach
def with_loop():
result = []
for i in range(1000):
result.append(i ** 2)
return result
# Comprehension approach
def with_comp():
return [i ** 2 for i in range(1000)]
print(timeit.timeit(with_loop, number=10000))
print(timeit.timeit(with_comp, number=10000)) # ~20-30% faster
When NOT to Use Comprehensions
Avoid comprehensions when they become hard to read:
# ❌ Too complex — use a regular loop
result = [
transform(x, y)
for x in range(10)
for y in range(10)
if x != y
if is_valid(x, y)
]
# ✅ Better as a loop
result = []
for x in range(10):
for y in range(10):
if x != y and is_valid(x, y):
result.append(transform(x, y))
Guidelines
| Use Comprehension When… | Use Loop When… |
|---|---|
| Simple transformation | Complex logic |
| One or two conditions | Multiple conditions |
| Result fits in one line | Side effects needed |
| Easy to read at a glance | Debugging required |
Dictionary and Set Comprehensions (Preview)
Python also supports comprehensions for other collections:
# Dictionary comprehension
squares_dict = {x: x ** 2 for x in range(6)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# Set comprehension
unique_lengths = {len(w) for w in ["hi", "hello", "hey"]}
print(unique_lengths) # {2, 5, 3}
We will cover these in detail in the Dictionaries and Sets chapters.
Summary
[expr for item in iterable]— basic comprehension[expr for item in iterable if cond]— with filter[a if cond else b for item in iterable]— with transform- Nested
forclauses for cartesian products and flattening - Prefer comprehensions for simple, readable transformations
- Fall back to regular loops for complex logic
Next up: Nested Lists →