Home/Learn/Python A–Z/Comprehensions — Lists, Dicts, Sets & Generator Expressions

Comprehensions — Lists, Dicts, Sets & Generator Expressions

Intermediate
Data Structures

Comprehensions build collections declaratively — [x*2 for x in nums if x > 0] — replacing 4-line loops with one readable line, with dict/set variants and lazy generator expressions.

Overview

Comprehensions are Python's signature idiom: transform + filter a collection in one expression that reads like math set notation. They are usually faster than equivalent for-loops (the loop runs in C), exist for lists, dicts and sets, and their lazy sibling — the generator expression — processes unlimited data in constant memory. Rule of taste: one, maybe two clauses. If a comprehension needs a paragraph to understand, write a loop.

The Anatomy: [expression for item in iterable if condition]

Map (expression), loop (for), filter (if) — in that order. An if/else BEFORE the for is a value choice; an if AFTER is a filter. Nesting reads left-to-right like nested loops.

All four comprehension forms
nums = [3, -1, 8, -5, 12]

positives_doubled = [n * 2 for n in nums if n > 0]   # [6, 16, 24]

# if/else as VALUE (before for) vs if as FILTER (after)
labels = ["pos" if n > 0 else "neg" for n in nums]
evens  = [n for n in nums if n % 2 == 0]

# Dict & set comprehensions
squares  = {n: n * n for n in range(5)}
lengths  = {len(w) for w in ["go", "py", "java"]}    # {2, 4}
inverted = {v: k for k, v in {"a": 1, "b": 2}.items()}

# Flatten a matrix — nested fors read left to right
matrix = [[1, 2], [3, 4], [5, 6]]
flat = [x for row in matrix for x in row]            # [1,2,3,4,5,6]

# Same as:
# for row in matrix:
#     for x in row: ...

Generator Expressions — Lazy Comprehensions

Round brackets make a generator: values are produced one at a time, on demand — constant memory. Feed them directly to sum/max/any/all without materializing a list.

() instead of [] — constant memory, short-circuit friendly
# List comp: builds ALL 10 million values in memory
# total = sum([n * n for n in range(10_000_000)])

# Generator expression: one value at a time — same result, ~no memory
total = sum(n * n for n in range(10_000_000))

# any/all short-circuit beautifully with generators
nums = [4, 8, 15, 16, 23, 42]
print(any(n > 40 for n in nums))       # True — stops at 42
print(all(n % 2 == 0 for n in nums))   # False — stops at 15

# Read a huge file lazily: total chars in long lines
# long = sum(len(line) for line in open("big.log") if len(line) > 80)

# A generator is one-shot
g = (n * 2 for n in [1, 2, 3])
print(list(g))    # [2, 4, 6]
print(list(g))    # [] — exhausted!

Key Points to Remember

  • 1Order: expression → for → if(filter); if/else before the for is a value expression
  • 2Dict: {k: v for ...}; set: {x for ...}; generator: (x for ...)
  • 3Generator expressions are lazy and one-shot — perfect inside sum/any/all/max
  • 4Two clauses max for readability — beyond that, write the loop

Interview Questions

Sign in to ask Aria
1

Flatten a list of lists with a comprehension — and explain the clause order.

MediumFlipkart
2

List comprehension vs generator expression — memory and reuse differences?

MediumAmazon
3

Invert a dictionary (values become keys) in one line. What could go wrong?

MediumRazorpay

Ask Aria about Comprehensions — Lists, Dicts, Sets & Generator Expressions

Your personal AI tutor — ask anything about this concept

Revision Status

Personal Notes

Sign in to save personal notes for this topic.

Discussion

Sign in to join the discussion.

Loading discussion…