Dataslope logoDataslope

Comprehensions

List, dict, set, and generator comprehensions

A comprehension is a compact way to build a list, dict, set, or generator by transforming and filtering an iterable. Comprehensions are arguably the most Pythonic feature in the language. They turn "loop over this, filter that, transform these" into a single readable expression. Once you internalize the pattern, you will reach for them constantly in data pipelines, API response shaping, config munging, and anywhere you transform collections.

Every snippet on this page runs in your browser — no setup required.

Real-world impact

Comprehensions are everywhere in production Python. Every data pipeline maps and filters rows with comprehensions. Every web API shapes JSON responses with dict comprehensions. Every script that processes files uses comprehensions to filter and transform lines. Mastering comprehensions means writing clearer, faster, more maintainable code.

List comprehensions: basics

The general form:

[expression for item in iterable if condition]
Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

A list comprehension is equivalent to:

result = []
for x in iterable:
    if condition:
        result.append(expression)

The comprehension is usually preferable because it states what you want rather than how. It is also often faster because the loop is optimized at the C level.

List comprehensions: with filter

The if clause is optional.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

You can combine transformation and filtering.

Code Block
Python 3.13.2

List comprehensions: nested loops

Multiple for clauses behave like nested loops, left to right.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Nested comprehensions are useful for flattening lists.

Code Block
Python 3.13.2

Readability ceiling

Comprehensions are powerful, but stacking too much logic into one makes for unreadable code. Rule of thumb: up to one for and one if is usually fine. More than that, or a complex expression, and you should write a loop. Comprehensions are for clarity, not cleverness.

Dict comprehensions

Use {key: value for ...} to build a dict.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Inverting a dict is a one-liner.

Code Block
Python 3.13.2

Dict comprehensions are especially useful when reshaping API responses or config files.

Code Block
Python 3.13.2

Set comprehensions

Use {expression for ...} to build a set.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

Set comprehensions automatically deduplicate, just like constructing set([...]) would.

Generator expressions

Drop the brackets and you get a generator expression instead. It produces items lazily, one at a time, which is great for memory efficiency.

Code Block
Python 3.13.2
Code Block
Python 3.13.2

The results are identical, but the generator uses O(1) memory while the list uses O(n).

Generator vs list memory

A list comprehension builds the entire list in memory before you can use it. A generator expression produces values on demand, one at a time. If you only need to iterate once (e.g., in sum, max, any, all), use a generator. If you need to iterate multiple times or slice the result, use a list.

When a generator expression is the only argument to a function, the inner parentheses can be dropped:

Code Block
Python 3.13.2

This is equivalent to sum((x * x for x in range(10))) but cleaner.

When to use each form

FormUse when
List comprehension [...]You need the full list, or will iterate multiple times
Dict comprehension {k: v ...}Building or transforming dicts
Set comprehension {...}Building a set, deduplication is important
Generator expression (...)One-time iteration, memory efficiency matters

Challenges

Challenge
Python 3.13.2
Squares of even numbers

Define even_squares(n) that returns a list of the squares of every even number from 0 to n-1, in order. Use a single list comprehension.

Challenge
Python 3.13.2
Group words by length

Define group_by_length(words) that returns a dict mapping each word length to a list of words with that length, preserving the input order within each group.

For example, group_by_length(["a", "bb", "cc", "d"]) returns {1: ["a", "d"], 2: ["bb", "cc"]}.

A regular loop is fine here; you do not have to use a single comprehension.

Challenge
Python 3.13.2
Cartesian product pairs

Define cartesian(a, b) that returns a list of all (x, y) pairs where x is from list a and y is from list b, in the order produced by nested loops. Use a single list comprehension with two for clauses.

For example, cartesian([1, 2], ["a", "b"]) returns [(1, "a"), (1, "b"), (2, "a"), (2, "b")].

QuestionSelect one

What does [x * 2 for x in range(4) if x % 2] evaluate to?

[0, 2, 4, 6]

[2, 6]

[1, 3]

[0, 4]

QuestionSelect one

Which of the following produces the same result as [x*x for x in range(5)]?

(x*x for x in range(5))

{x*x for x in range(5)}

list(x*x for x in range(5))

{x: x*x for x in range(5)}

QuestionSelect one

What is the key advantage of a generator expression over a list comprehension?

Generators are always faster.

Generators use O(1) memory regardless of input size.

Generators support slicing.

Generators automatically deduplicate.

QuestionSelect one

What does this nested comprehension produce?

[x + y for x in [1, 2] for y in [10, 20]]

[11, 22]

[11, 21, 12, 22]

[11, 12, 21, 22]

[30, 40]

You can now turn raw iterables into shaped data in one line. Functions are next.

On this page