Aller au contenu principal

02.3 - List, Dict & Set Comprehensions

Theory 20 min Intermediate

What is a Comprehension?

A comprehension is a compact, readable way to create a new collection by transforming or filtering an existing iterable — in a single line.

# Traditional loop
squares = []
for n in range(10):
squares.append(n ** 2)

# List comprehension — equivalent, 1 line
squares = [n ** 2 for n in range(10)]
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Python supports 4 types of comprehensions:

TypeSyntaxReturns
List[expr for x in iterable]list
Dict{k: v for x in iterable}dict
Set{expr for x in iterable}set
Generator(expr for x in iterable)generator

List Comprehensions

Basic Syntax

[expression for variable in iterable]
[expression for variable in iterable if condition]
# All squares from 0 to 9
squares = [x ** 2 for x in range(10)]

# Even numbers only (with filter)
evens = [x for x in range(20) if x % 2 == 0]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Strings to uppercase
words = ["hello", "world", "python"]
upper = [w.upper() for w in words]
# ['HELLO', 'WORLD', 'PYTHON']

# Extract lengths
lengths = [len(w) for w in words]
# [5, 5, 6]

With Conditional Expression (if/else)

# if/else inside expression (transform, not filter)
numbers = [-3, -1, 0, 2, 5, -4, 7]
abs_values = [n if n >= 0 else -n for n in numbers]
# [3, 1, 0, 2, 5, 4, 7]

# Label positive/negative
labels = ["positive" if n > 0 else "negative" if n < 0 else "zero"
for n in numbers]

Nested Comprehensions

# Flatten a 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

# Cartesian product
pairs = [(x, y) for x in [1, 2, 3] for y in ["a", "b"]]
# [(1,'a'), (1,'b'), (2,'a'), (2,'b'), (3,'a'), (3,'b')]

Dict Comprehensions

# Basic: {key: value for item in iterable}
squares_dict = {x: x**2 for x in range(6)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

# Swap keys and values
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
# {1: "a", 2: "b", 3: "c"}

# Filter a dict (keep values > 10)
prices = {"apple": 1.5, "laptop": 999, "book": 25, "pen": 2}
expensive = {k: v for k, v in prices.items() if v > 10}
# {"laptop": 999, "book": 25}

# Normalize text keys
raw = {" Name ": "Alice", " Age ": 30}
clean = {k.strip().lower(): v for k, v in raw.items()}
# {"name": "Alice", "age": 30}

Set Comprehensions

# Remove duplicates and square
numbers = [1, 2, 2, 3, 3, 4]
unique_squares = {n ** 2 for n in numbers}
# {1, 4, 9, 16} — order not guaranteed

# Unique first letters
words = ["apple", "avocado", "banana", "blueberry", "cherry"]
first_letters = {w[0] for w in words}
# {'a', 'b', 'c'}

Generator Expressions

A generator expression looks like a list comprehension but uses () and generates values lazily — one at a time, without storing everything in memory.

# List comprehension — creates full list in memory
squares_list = [x ** 2 for x in range(1_000_000)] # uses ~8MB

# Generator expression — computes on demand
squares_gen = (x ** 2 for x in range(1_000_000)) # uses ~200 bytes!

# Use with sum(), min(), max(), any(), all()
total = sum(x ** 2 for x in range(100)) # no [] needed!
max_val = max(len(w) for w in ["hi", "hello", "hey"])

# Check: are all numbers positive?
numbers = [1, 3, 5, 7, 9]
all_positive = all(n > 0 for n in numbers) # True

# Check: is any number negative?
any_negative = any(n < 0 for n in numbers) # False

When to Use Comprehensions


Comprehension vs Loop — Style Guide

# ✅ Use comprehension: single, clear transformation
names = [user["name"] for user in users if user["active"]]

# ❌ Avoid: multiple operations — use a regular loop instead
result = []
for user in users:
if user["active"]:
processed = process(user)
if processed:
result.append(processed)

Rule: Comprehensions should be readable in one line. If it needs 3+ conditions or nested logic, use a for loop.


Real-World Examples

import os

# List all Python files in current directory
py_files = [f for f in os.listdir(".") if f.endswith(".py")]

# Build a word frequency dict
text = "the quick brown fox jumps over the lazy dog the fox"
freq = {}
for word in text.split():
freq[word] = freq.get(word, 0) + 1

# Same with dict comprehension + Counter
from collections import Counter
freq = dict(Counter(text.split()))

# Parse CSV data
csv_data = ["Alice,30,Montreal", "Bob,25,Toronto", "Charlie,35,Vancouver"]
people = [
{"name": row[0], "age": int(row[1]), "city": row[2]}
for line in csv_data
for row in [line.split(",")]
]

Key Vocabulary

TermDefinition
ComprehensionCompact syntax to create a collection from an iterable
List comprehension[expr for x in iterable if cond] — creates a list
Dict comprehension{k: v for x in iterable} — creates a dict
Set comprehension{expr for x in iterable} — creates a set (unique)
Generator expression(expr for x in iterable) — lazy evaluation, memory-efficient
Lazy evaluationValues computed on demand, not all at once
any() / all()Check if any/all elements satisfy a condition

Summary

  • List comprehensions [expr for x in iterable if cond] replace simple for + append loops
  • Dict comprehensions {k: v for ...} build dicts from iterables in one line
  • Set comprehensions {expr for ...} create sets (automatically deduplicate)
  • Generator expressions (expr for ...) compute values lazily — use with large data
  • Use sum(), min(), max(), any(), all() directly with generators — no [] needed
  • Keep comprehensions simple: if you need 3+ operations, use a regular loop