List, dict, and set comprehensions are Python's signature feature for transforming collections. They're more compact than loops, more idiomatic, and slightly faster. Get fluent with them and your code will look like the Python you read in textbooks and on Stack Overflow.
List comprehension — the basic shape
# Loop versionsquared = []for x in [1, 2, 3, 4, 5]:squared.append(x ** 2)# Comprehension versionsquared = [x ** 2 for x in [1, 2, 3, 4, 5]]# [1, 4, 9, 16, 25]
Filtering with if
rates = [0.07, 0.10, 0.12, 0.15, 0.08]# Above-average rates onlyhigh = [r for r in rates if r > 0.10]# [0.12, 0.15]# Tag each rate as 'high' or 'low'tagged = ['high' if r > 0.10 else 'low' for r in rates]# Note: the if/else here is the ternary expression, not a filter
Dict and set comprehensions
# Dict — map keys to derived valuesbanks = ['KCB', 'Equity', 'Coop']lengths = {b: len(b) for b in banks}# {'KCB': 3, 'Equity': 6, 'Coop': 4}# Set — collect unique resultsfirst_letters = {b[0] for b in banks}# {'K', 'E', 'C'}
Nested comprehensions
You can write nested comprehensions, but they get hard to read fast. The rule: if the comprehension reads as a single English sentence, use it. If you have to mentally parse the order of fors and ifs, use a normal loop.
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]flat = [x for row in matrix for x in row]# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Generator expressions
If you replace the outer brackets with parentheses, you get a generator expression — a lazy version of the comprehension that produces values on demand instead of materialising a list. Useful for large data: sum(x ** 2 for x in range(10**6)) doesn't build the squared list, just streams through it.
Lambda functions
lambda x: x ** 2 is an anonymous function — useful as an inline argument to map, filter, sorted. Outside of those contexts, prefer named functions: a one-line lambda is concise; a multi-step lambda is unreadable.
Exercise
Given rates = [0.07, 0.10, 0.12, 0.15, 0.08], use a list comprehension to produce a list of those above 0.10.