Contact
Evil Genius SocietyHomeLearnForumLeaderboardSocialsMessages
← Back to module

Lesson 1 of 10

Module 3 covered list comprehensions. The same syntax builds dictionaries and sets, and handles more complex shapes.

Dict comprehensions

Curly braces with a key: value pair:

numbers = [1, 2, 3, 4]
squares = {n: n ** 2 for n in numbers}
print(squares)

Transforming an existing dictionary is the most common use:

prices = {"apple": 1.0, "banana": 0.5, "cherry": 3.0}

doubled = {name: price * 2 for name, price in prices.items()}
print(doubled)

cheap = {name: price for name, price in prices.items() if price < 2}
print(cheap)

flipped = {price: name for name, price in prices.items()}
print(flipped)

Two useful patterns — building a lookup table from records, and normalising keys:

people = [
    {"id": 1, "name": "Ada"},
    {"id": 2, "name": "Grace"},
]

by_id = {p["id"]: p["name"] for p in people}
print(by_id)

config = {"THEME": "dark", "Font": "mono"}
print({k.lower(): v for k, v in config.items()})

Set comprehensions

Same braces, no colon:

words = ["apple", "banana", "avocado", "blueberry"]

first_letters = {w[0] for w in words}
print(sorted(first_letters))

lengths = {len(w) for w in words}
print(sorted(lengths))

Duplicates disappear automatically — that's the point.

Conditional expressions inside

An if at the end filters. An if/else before the for transforms:

numbers = [1, 2, 3, 4, 5, 6]

print([n for n in numbers if n % 2 == 0])
print(["even" if n % 2 == 0 else "odd" for n in numbers])

The difference is worth internalising: a trailing if chooses which items to keep; a leading if/else chooses what value each item becomes. You can combine both:

numbers = [1, 2, 3, 4, 5, 6]
print(["big" if n > 4 else "small" for n in numbers if n % 2 == 0])

Nested loops

Two for clauses read in the same order you'd write the nested loop:

pairs = [(x, y) for x in [1, 2] for y in ["a", "b"]]
print(pairs)

Flattening a nested list is the classic case:

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

flat = [n for row in matrix for n in row]
print(flat)

evens = [n for row in matrix for n in row if n % 2 == 0]
print(evens)

You can also nest a comprehension inside a comprehension:

matrix = [[1, 2], [3, 4]]
doubled = [[n * 2 for n in row] for row in matrix]
print(doubled)

Know when to stop

Comprehensions are for building a collection from another one. Once you need multiple conditions, nested loops, and a transformation all at once, a plain loop is clearer:

matrix = [[1, 2, 3], [4, 5, 6]]

result = [n * 2 for row in matrix for n in row if n % 2 == 0 if n > 2]
print(result)

result = []
for row in matrix:
    for n in row:
        if n % 2 == 0 and n > 2:
            result.append(n * 2)
print(result)

Both work. The second is easier to debug and easier to explain. Readability wins — that's the Pythonic instinct, and lesson 9.8 returns to it.

Try it yourself

Checkpoint

  • {k: v for ...} builds a dict; {x for ...} builds a set.
  • A trailing if filters; a leading if/else transforms.
  • Multiple for clauses read left to right, like nested loops.
  • Stop and use a loop when the comprehension stops being readable.

Questions about this lesson

Log in to ask a question.