What are list comprehensions and how do they work?
A list comprehension is a concise way to create lists from iterables:
[expression for item in iterable if condition]
It is equivalent to:
result = []
for item in iterable:
if condition:
result.append(expression)
Advantages over loops:
- More concise and readable for simple transforms
- Slightly faster (optimized C loop internally)
- Clearly communicates intent (creating a list)
Components:
- Expression: What to put in the new list
- Iteration:
for item in iterable - Filter (optional):
if condition
List comprehensions can also include multiple for clauses (nested) and multiple if clauses.
Basic: [expr for x in iterable]
Filtered: [expr for x in iterable if condition]
Transform + filter: [f(x) for x in iterable if g(x)]
Nested: [expr for x in iter1 for y in iter2]
Equivalent loop:
result = []
for x in iterable:
if condition:
result.append(expr)
# Basic list comprehension
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# With filter
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# Transform + filter
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
# With function call
words = ["hello", "world", "python"]
upper_words = [w.upper() for w in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
# Conditional expression (ternary) in comprehension
labels = ["even" if x % 2 == 0 else "odd" for x in range(5)]
print(labels) # ['even', 'odd', 'even', 'odd', 'even']
# Note the difference: filter vs ternary
# Filter (if at end): controls WHICH items to include
filtered = [x for x in range(10) if x > 5]
print(filtered) # [6, 7, 8, 9]
# Ternary (if in expression): transforms ALL items
transformed = [x if x > 5 else 0 for x in range(10)]
print(transformed) # [0, 0, 0, 0, 0, 0, 6, 7, 8, 9]
# String processing
names = [" alice ", "BOB", " Charlie "]
cleaned = [name.strip().title() for name in names]
print(cleaned) # ['Alice', 'Bob', 'Charlie']
# Type conversion
string_nums = ["1", "2", "3", "4", "5"]
nums = [int(s) for s in string_nums]
print(nums) # [1, 2, 3, 4, 5]
# Performance comparison
import timeit
# List comprehension
comp_time = timeit.timeit(lambda: [x**2 for x in range(1000)], number=10000)
# Equivalent loop
def loop_version():
result = []
for x in range(1000):
result.append(x**2)
return result
loop_time = timeit.timeit(loop_version, number=10000)
print(f"Comprehension: {comp_time:.4f}s")
print(f"Loop: {loop_time:.4f}s") # typically slower
- •Syntax: [expression for item in iterable if condition]
- •Filter (if at end) selects which items to include
- •Ternary (if in expression) transforms all items
- •Faster than equivalent for loop (optimized internally)
- •Best for simple transforms -- use loops for complex logic
- •Do not confuse filter (if at end) with ternary (if in expression)
- •List comprehensions create the entire list in memory at once
- •Complex comprehensions hurt readability -- use loops instead
- •Variables in comprehensions do NOT leak into enclosing scope (Python 3)