Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Python
  3. Python Comprehensions Practice: List, Dict, Set & Generator Expressions
Python37 exercises

Python Comprehensions Practice: List, Dict, Set & Generator Expressions

Practice Python dict and list comprehensions with short write-from-memory drills. Covers if vs if-else, nested for order, and generators.

Cheat SheetCommon ErrorsQuick ReferencePractice
Warm-up1 / 2

Can you write this from memory?

Create a dict mapping numbers 1-3 to their squares using a dict comprehension

On this page
  1. 1Cheat sheet: all four comprehension types
  2. 2Filtering with if (exclude items)
  3. 3If-else in comprehensions (transform all items)
  4. 4Nested for-clauses: the order rule
  5. Common pattern: flatten a 2D list
  6. 5Dict and set comprehensions
  7. 6Generator expressions: lazy evaluation
  8. The gotcha: leftmost iterable is evaluated immediately
  9. 7Scope: the iteration variable doesn't leak
  10. 8Pro tip: the walrus operator (:=)
  11. 9Loop ↔ comprehension translation
  12. Example 1: Map (transform each item)
  13. Example 2: Filter (keep some items)
  14. Example 3: Filter + transform
  15. Example 4: Nested loops (flatten)
  16. 10When to avoid comprehensions
  17. 11References
Cheat sheet: all four comprehension typesFiltering with if (exclude items)If-else in comprehensions (transform all items)Nested for-clauses: the order ruleDict and set comprehensionsGenerator expressions: lazy evaluationScope: the iteration variable doesn't leakPro tip: the walrus operator (:=)Loop ↔ comprehension translationWhen to avoid comprehensionsReferences

Python comprehensions look easy in tutorials. Then you're typing one live and blank on where the if goes, or you nest two for clauses and flip the order.

The patterns aren't complicated, but they need to be automatic. These exercises drill the syntax until you stop second-guessing yourself.

The four types:

  • [expr for x in xs] → list (like map)
  • [expr for x in xs if cond] → filtered list
  • {k: v for ...} / {expr for ...} → dict / set
  • (expr for ...) → generator (lazy)
Related Python Topics
Python Loops: range(), enumerate(), zip(), break/continue, for-elsePython Function Arguments: defaults, *args, keyword-only, **kwargsPython Collections: Lists, Dicts, Sets & Tuples

Square brackets build a list, curly braces build a dict or set (dict if there's a colon), parentheses build a lazy generator.

PatternWhat it buildsExample
[expr for x in xs]list[x**2 for x in range(5)] → [0, 1, 4, 9, 16]
[expr for x in xs if cond]filtered list[x for x in nums if x > 0]
{k: v for x in xs}dict{w: len(w) for w in words}
{expr for x in xs}set{x.lower() for x in names}
(expr for x in xs)generator (lazy)sum(x*x for x in nums)

For a printable quick reference, see the Python list comprehensions cheat sheet.


Ready to practice?

Start practicing Python Comprehensions: List, Dict, Set & Generator Expressions with spaced repetition

Filter if goes after the iterable and excludes items. Ternary if-else goes before the for and transforms all items.

The filter if comes after the iterable:

[expression for variable in iterable if condition]

Think of it as "for each x in xs, if condition is true, include it."

# Only include positives (others are excluded)
positives = [x for x in nums if x > 0]

# Multiple conditions (same as "and")
valid = [x for x in items if x > 0 if x < 100]
# Equivalent to: if x > 0 and x < 100

The if-else goes before the for—it's part of the expression, not a filter:

[value_if_true if condition else value_if_false for variable in iterable]

This transforms every item—nothing is excluded.

# Transform all: positive stays, negative becomes 0
clamped = [x if x > 0 else 0 for x in nums]

# Classify each item
labels = ["even" if x % 2 == 0 else "odd" for x in nums]

Key difference:

  • Filter if (at end): excludes items → shorter list
  • Ternary if-else (at start): transforms all → same length

Read left-to-right: the first for is the outermost loop, the next for is inside it.

The for-clauses read in the same order as nested loops.

This comprehension:

flat = [x for row in matrix for x in row]

Is equivalent to:

flat = []
for row in matrix:      # leftmost = outer
    for x in row:       # next = inner
        flat.append(x)

Memory trick: Read left-to-right. The first for is the outermost loop. If the nesting maps exactly to a standard loop pattern, the comprehension version reads in the same order.

Common pattern: flatten a 2D list

matrix = [[1, 2], [3, 4], [5, 6]]
flat = [n for row in matrix for n in row]
# → [1, 2, 3, 4, 5, 6]

Dict comprehension uses {key: value for ...}:

# Word → length mapping
word_lengths = {word: len(word) for word in words}

# Invert a dict (swap keys and values)
inverted = {v: k for k, v in original.items()}

# Filter a dict
expensive = {k: v for k, v in prices.items() if v > 100}

Set comprehension uses {expr for ...} (no colon). Sets are ideal when you need uniqueness — see the collections guide for when to choose sets over lists:

# Unique lowercase names
unique_names = {name.lower() for name in names}

# Unique first characters
initials = {word[0] for word in words if word}

A generator expression looks like a list comprehension with parentheses:

# List comprehension: builds entire list in memory
squares_list = [x**2 for x in range(1_000_000)]

# Generator expression: lazy, one value at a time
squares_gen = (x**2 for x in range(1_000_000))

When to use generators:

  • You only iterate once
  • The data is large and you don't need it all in memory
  • You're passing directly to a function like sum(), any(), all()
# No intermediate list allocated
total = sum(x**2 for x in nums)
has_negative = any(x < 0 for x in nums)
all_positive = all(x > 0 for x in nums)

The gotcha: leftmost iterable is evaluated immediately

def get_items():
    print("Fetching items...")
    return [1, 2, 3]

# This prints "Fetching items..." RIGHT NOW, not when you iterate
gen = (x**2 for x in get_items())

The generator is lazy for producing values, but the source iterable is evaluated when you create the generator.


In Python 3, comprehensions have their own scope:

x = "original"
result = [x for x in range(3)]
print(x)  # Still "original"—x wasn't overwritten

This is different from regular for loops, where the variable persists:

x = "original"
for x in range(3):
    pass
print(x)  # 2—the loop variable leaked

A common inefficiency is calling an expensive function twice:

# BAD: calls process() twice per item
results = [process(x) for x in data if process(x) > threshold]

The walrus operator (Python 3.8+) lets you assign and test in one step:

# GOOD: calls process() once, reuses the result
results = [y for x in data if (y := process(x)) > threshold]

This is especially useful when the filter condition uses the same computed value you want in the output.


Example 1: Map (transform each item)

Loop version:

squares = []
for x in range(10):
    squares.append(x ** 2)

Comprehension:

squares = [x ** 2 for x in range(10)]

Example 2: Filter (keep some items)

Loop version:

evens = []
for x in nums:
    if x % 2 == 0:
        evens.append(x)

Comprehension:

evens = [x for x in nums if x % 2 == 0]

Example 3: Filter + transform

Loop version:

squared_evens = []
for x in nums:
    if x % 2 == 0:
        squared_evens.append(x ** 2)

Comprehension:

squared_evens = [x ** 2 for x in nums if x % 2 == 0]

Example 4: Nested loops (flatten)

Loop version:

flat = []
for row in matrix:
    for item in row:
        flat.append(item)

Comprehension:

flat = [item for row in matrix for item in row]

Use a regular loop when:

  1. You need side effects (printing, logging, mutating external state)

    # Bad: comprehension for side effects
    [print(x) for x in items]  # returns [None, None, ...]
    
    # Good: just use a loop
    for x in items:
        print(x)
    
  2. It's getting hard to read (2+ for-clauses + 2+ conditions)

    # Hard to parse
    result = [f(x, y) for x in xs if p(x) for y in ys if q(x, y)]
    
    # Clearer as a loop or helper function
    
  3. You need early exit (break/continue logic)

  4. The expression is complex enough to deserve a name


  • Python Tutorial: List Comprehensions
  • Python Tutorial: Nested List Comprehensions
  • Python Reference: Displays for lists, sets and dictionaries
  • Python Reference: Generator expressions

When to Use Python Comprehensions: List, Dict, Set & Generator Expressions

  • Transform or filter an iterable into a new list/set/dict in one readable expression.
  • Replace short "accumulator loops" whose intent is purely map/filter.
  • Use a **generator expression** when you only need to iterate once and don't want to allocate a whole list.

Check Your Understanding: Python Comprehensions: List, Dict, Set & Generator Expressions

Prompt

Given a list of orders, return the ids of orders over $100.

What a strong answer looks like

Use a filter + projection: `[o.id for o in orders if o.total > 100]`. It's clearer than a manual accumulator when the intent is "filter then map".

What You'll Practice: Python Comprehensions: List, Dict, Set & Generator Expressions

Basic [expr for x in xs] syntaxFiltering with ifIf-else (ternary) inside comprehensionsMultiple for-clauses (nested loops)Dict comprehensions {k: v for ...}Set comprehensions {expr for ...}Generator expressions (expr for ...)Walrus operator (:=) for filter-and-use patterns

Common Python Comprehensions: List, Dict, Set & Generator Expressions Pitfalls

  • Flipping the order in nested comprehensions—for-clauses match nested loop order (leftmost is outer)
  • Forgetting brackets vs parentheses: `[...]` builds a list, `(...)` is a generator
  • Trying to do side effects in a comprehension—use a loop for mutations
  • Missing parentheses when the expression is a tuple: `[(x, y) for ...]` not `[x, y for ...]`
  • Assuming the iteration variable leaks into outer scope (it doesn't since Python 3)
  • Lambda closure trap: `[lambda: x for x in range(3)]` all return 2—use `lambda x=x: x` to capture
  • Confusing filter `if` (at end, excludes items) with ternary `if-else` (at start, transforms all)

Python Comprehensions: List, Dict, Set & Generator Expressions FAQ

Where does the if go in a list comprehension?

For **filtering**, the `if` comes after the iterable: `[expr for x in xs if cond]`. For **if-else transformation**, put it before: `[a if cond else b for x in xs]`. Filtering excludes items; if-else transforms all items.

What order do nested for-clauses run in?

Same as nested loops: the **leftmost** `for` is the outer loop, the next `for` is inside it. `[x for row in matrix for x in row]` is equivalent to nested `for row in matrix: for x in row:`.

Why isn't my loop variable available after the comprehension?

Comprehensions execute in an implicitly nested scope (since Python 3), so the iteration variable doesn't "leak" into the surrounding scope. This is intentional—it prevents accidental variable shadowing.

Generator expression vs list comprehension?

A list comprehension builds the whole list immediately. A generator expression is **lazy**: it produces values as you iterate. One gotcha: the leftmost iterable is evaluated immediately when the generator is created, so errors can happen at definition time.

Are comprehensions faster than for loops?

Yes, typically 10–30% faster for simple transformations. Comprehensions compile to a dedicated LIST_APPEND bytecode instruction that avoids the per-iteration attribute lookup and method call overhead of .append(). But treat performance as a bonus—readability and correctness come first. Measure if it matters.

When should I avoid a comprehension?

When it has 2+ `for` clauses + 2+ conditions, consider a loop or helper function. If you need side effects (printing, mutating external state), don't use a comprehension—they're for building containers, not running actions.

Can I use multiple if conditions?

Yes: `[x for x in xs if cond1 if cond2]` is valid—it means `cond1 and cond2`. Most prefer the explicit `and` for clarity, but you'll see chained `if`s in legacy code.

What is a dict comprehension in Python?

A dict comprehension builds a dictionary in one expression: `{key: value for item in iterable}`. It's the dict equivalent of a list comprehension. Example: `{word: len(word) for word in words}` creates a word-to-length mapping.

How do you create a map comprehension in Python?

Python doesn't have a literal "map comprehension." The term usually means a dict comprehension (`{k: v for ...}`) that maps keys to values, or using the built-in `map()` function. For a dictionary, use `{k: transform(k) for k in keys}`.

Python Comprehensions: List, Dict, Set & Generator Expressions Syntax Quick Reference

Map (basic)
squares = [x**2 for x in range(10)]
Filter
evens = [x for x in nums if x % 2 == 0]
Nested for (flatten)
flat = [n for row in matrix for n in row]
Dict comprehension
lengths = {word: len(word) for word in words}
Set comprehension
unique = {name.lower() for name in names if name}
Generator expression
total = sum(x*x for x in nums)  # no list allocated
Conditional (ternary)
labels = ["even" if x % 2 == 0 else "odd" for x in nums]
Tuple in comprehension
pairs = [(i, x) for i, x in enumerate(items)]
Walrus operator (:=)
results = [y for x in data if (y := expensive(x)) > 0]
Multiple if conditions
valid = [x for x in items if x > 0 if x < 100]  # same as: and

Python Comprehensions: List, Dict, Set & Generator Expressions Sample Exercises

Example 1Difficulty: 2/5

What does this dict comprehension create?

{1: 2, 2: 4, 3: 6}
Example 2Difficulty: 3/5

Create a dict mapping numbers 1-5 to their squares, but only for even numbers

{n: n**2 for n in range(1, 6) if n % 2 == 0}
Example 3Difficulty: 2/5

Create a new dict by swapping keys and values from `item_map`

{v: k for k, v in item_map.items()}

+ 34 more exercises

Quick Reference
Python Comprehensions: List, Dict, Set & Generator Expressions Cheat Sheet →

Copy-ready syntax examples for quick lookup

Further Reading

  • GDScript Dictionary map() and map_in_place12 min read

Start practicing Python Comprehensions: List, Dict, Set & Generator Expressions

Free daily exercises with spaced repetition. No credit card required.

← Back to Python Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.