Tech With Galvan

List & Dict Comprehensions

25 min • Beginner • Module 10

Transform collections in one readable line — the #1 Pythonic skill.

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

  • NameError on the loop variable outside — the variable leaks after the comprehension in some Python versions; don’t rely on it existing.
  • SyntaxError with if/else placement — filter-if goes at the END ([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!
  • Missing brackets — comprehensions live inside [] or {}; a bare comprehension is a syntax error.

✅ Checkpoint

  1. Comprehension for cubes of 1–5? ([n ** 3 for n in range(1, 6)])
  2. Keep only strings longer than 5 from words? ([w for w in words if len(w) > 5])
  3. Build {word: len(word)} from a list? ({w: len(w) for w in words})
  4. Where does the filter-if go vs the if-else transform? (Filter: end. If-else: front.)

Next: generators — producing values lazily and handling infinite sequences.