Difficulty: Beginner
Explain list comprehensions in Python. How do they compare to loops?
List comprehensions provide a concise way to create lists based on existing iterables. They are generally faster than equivalent for-loop constructions because they are optimized at the C level in CPython.
Syntax: [expression for item in iterable if condition]
Types of comprehensions: - List: [x for x in range(10)] - Dict: {k: v for k, v in items} - Set: {x for x in range(10)} - Generator expression: (x for x in range(10)) - lazy evaluation
Comprehensions should be readable. If they get too complex (multiple conditions, deep nesting), use a regular loop instead.
# Simple transformation
squares = [x 2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# With filtering
evens = [x for x in range(20) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# 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']
# String processing
words = [' Hello ', ' World ', ' Python ']
cleaned = [w.strip().lower() for w in words]
print(cleaned) # ['hello', 'world', 'python']
# Flattening with method calls
sentences = ['hello world', 'foo bar baz']
all_words = [word for sentence in sentences for word in sentence.split()]
print(all_words) # ['hello', 'world', 'foo', 'bar', 'baz']
The if clause filters items. Ternary expressions (x if cond else y) transform each item. Nested for clauses flatten nested structures.
# Dict comprehension
word_lengths = {word: len(word) for word in ['hello', 'world', 'python']}
print(word_lengths) # {'hello': 5, 'world': 5, 'python': 6}
# Set comprehension (auto-deduplicates)
first_letters = {word[0] for word in ['apple', 'avocado', 'banana', 'blueberry']}
print(first_letters) # {'a', 'b'}
# Nested comprehension: 2D matrix
matrix = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrix) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
# Flatten a matrix
flat = [val for row in matrix for val in row]
print(flat) # [1, 2, 3, 2, 4, 6, 3, 6, 9]
# Transpose a matrix
transposed = [[row[i] for row in matrix] for i in range(3)]
print(transposed) # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]
Comprehensions work for dicts and sets too. Nested comprehensions read left-to-right matching nested for-loop order.
import time
# Loop approach
start = time.time()
result = []
for i in range(1_000_000):
result.append(i 2)
loop_time = time.time() - start
# Comprehension approach
start = time.time()
result = [i 2 for i in range(1_000_000)]
comp_time = time.time() - start
print(f"Loop: {loop_time:.4f}s")
print(f"Comprehension: {comp_time:.4f}s")
print(f"Speedup: {loop_time / comp_time:.1f}x")
# When NOT to use comprehension
# Bad: too complex, hard to read
# result = [transform(x) for x in data if validate(x) for y in x.items() if check(y)]
# Better: use a regular loop
result = []
for x in data:
if validate(x):
for y in x.items():
if check(y):
result.append(transform(x))
Comprehensions are faster because they avoid the overhead of list.append() method lookup on each iteration. But readability matters more than micro-optimization.
List Comprehension, Dict Comprehension, Set Comprehension, Nested Comprehension, Filtering