List & Dict Comprehensions
Remember building lists with loops — empty list, append inside, three lines? Comprehensions do it in one line, and they're the single most "Pythonic" skill in the language. Code that uses them *reads* like Python was meant to read.
The upgrade path
The loop you know:
squares = []
for n in range(1, 6):
squares.append(n ** 2)
print(squares) # [1, 4, 9, 16, 25]The comprehension — same result, one line:
squares = [n ** 2 for n in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]Read the comprehension left to right as a sentence: *"give me n squared, for each n in range 1 to 6."* The expression comes first, the loop after — backwards from a for loop, but natural once you read it as the outcome you're collecting.
Adding a condition: the filter
numbers = [1, 2, 3, 4, 5, 6, 7, 8]
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8]
big_evens = [n for n in numbers if n % 2 == 0 and n > 4]
print(big_evens) # [6, 8]An if at the end keeps only matching items. Full sentence: *"give me n, for each n in numbers, if n is even."*
Transform AND filter together
words = ["apple", "banana", "avocado", "cherry", "apricot"]
a_words = [w.upper() for w in words if w.startswith("a")]
print(a_words) # ['APPLE', 'AVOCADO', 'APRICOT']Expression (transform) + loop (source) + condition (filter) — the three-part anatomy of every comprehension.
Dictionary comprehensions
Same idea, building dicts — {key: value for ...}:
marks = {"Aarav": 92, "Diya": 95, "Kabir": 78}
# invert a dict
inverted = {v: k for k, v in marks.items()}
print(inverted) # {92: 'Aarav', 95: 'Diya', 78: 'Kabir'}
# filter + transform
toppers = {name: mark for name, mark in marks.items() if mark > 80}
print(toppers) # {'Aarav': 92, 'Diya': 95}
# word lengths
words = ["apple", "banana", "kiwi"]
lengths = {w: len(w) for w in words}
print(lengths) # {'apple': 5, 'banana': 6, 'kiwi': 4}That last one — building a dict from a list — is a comprehension you'll write weekly.
Real-world one-liners you'll actually use
# clean a messy list of strings
raw = [" Aarav ", "DIYA", " kabir "]
names = [name.strip().title() for name in raw]
print(names) # ['Aarav', 'Diya', 'Kabir']
# numbers from strings (the input-conversion pattern!)
raw_input = ["10", "20", "30"]
values = [int(x) for x in raw_input]
# flatten a list of lists
grid = [[1, 2], [3, 4], [5, 6]]
flat = [num for row in grid for num in row]
print(flat) # [1, 2, 3, 4, 5, 6]That last one has TWO for clauses — "for each row in grid, for each num in row." Nested loops in one line. Readable? Debatable. Useful? Extremely.
When NOT to comprehend
If the logic needs multiple steps, try/except, or more than one condition plus a transform — use a regular loop. A comprehension you can't read in one breath is worse than a loop:
# ❌ too clever — nobody wants to parse this
result = [process(x) for x in data if x.valid and x.size > 10 and not x.skip and check(x)]
# ✅ a loop is honest about complexity
result = []
for x in data:
if x.valid and x.size > 10 and not x.skip and check(x):
result.append(process(x))Comprehensions are for *one clear transformation*, not for hiding complexity.
Common Errors & Fixes
[x for x in xs if cond]); transform-if-else goes at the FRONT ([x if cond else y for x in xs]). Different positions, different jobs![] or {}; a bare comprehension is a syntax error.✅ Checkpoint
words? *([w for w in words if len(w) > 5])*{word: len(word)} from a list? *({w: len(w) for w in words})*Next: generators — producing values lazily and handling infinite sequences.