List Comprehensions
List comprehensions are one of Python's most beloved features. They provide a concise, readable way to create lists from existing iterables. A list comprehension combines a loop, an optional condition, and an expression into a single line.
# Basic syntax: [expression for item in iterable if condition]
# Simple transformation
numbers = [1, 2, 3, 4, 5]
squares = [n ** 2 for n in numbers]
print(squares) # [1, 4, 9, 16, 25]
# With filtering
evens = [n for n in range(20) if n % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
# String processing
words = ["Hello", "World", "Python", "Is", "Great"]
upper = [w.upper() for w in words]
long_words = [w for w in words if len(w) > 4]
# Conditional expression in the output
labels = ["even" if n % 2 == 0 else "odd" for n in range(6)]
print(labels) # ['even', 'odd', 'even', 'odd', 'even', 'odd']
# Flattening a 2D list
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Equivalent nested loop:
# flat = []
# for row in matrix:
# for num in row:
# flat.append(num)
# Nested comprehension (creating a 2D structure)
multiplication_table = [[i * j for j in range(1, 6)] for i in range(1, 6)]
for row in multiplication_table:
print(row)
Dictionary Comprehensions
Dictionary comprehensions create dictionaries using a similar syntax. They are especially useful for transforming, filtering, or inverting dictionaries.
# Basic dict comprehension
squares_dict = {n: n ** 2 for n in range(6)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# From two lists
keys = ["name", "age", "city"]
values = ["Alice", 30, "NYC"]
person = {k: v for k, v in zip(keys, values)}
print(person) # {'name': 'Alice', 'age': 30, 'city': 'NYC'}
# Filtering a dictionary
scores = {"Alice": 92, "Bob": 67, "Charlie": 85, "Diana": 45}
passed = {name: score for name, score in scores.items() if score >= 70}
print(passed) # {'Alice': 92, 'Charlie': 85}
# Inverting a dictionary
original = {"a": 1, "b": 2, "c": 3}
inverted = {v: k for k, v in original.items()}
print(inverted) # {1: 'a', 2: 'b', 3: 'c'}
# Transforming keys or values
prices = {"apple": 1.50, "banana": 0.75, "cherry": 2.00}
discounted = {item: price * 0.9 for item, price in prices.items()}
upper_keys = {k.upper(): v for k, v in prices.items()}
Set Comprehensions
# Set comprehension (like list comp but with curly braces)
words = ["hello", "world", "hello", "python", "world"]
unique_lengths = {len(w) for w in words}
print(unique_lengths) # {5, 6}
# Extract unique first characters
first_chars = {w[0].upper() for w in words}
print(first_chars) # {'H', 'W', 'P'}
# Practical: find all unique file extensions
files = ["main.py", "utils.py", "style.css", "index.html", "test.py"]
extensions = {f.split(".")[-1] for f in files}
print(extensions) # {'py', 'css', 'html'}
Walrus Operator in Comprehensions (Python 3.8+)
# The walrus operator := assigns and returns a value
# Useful to avoid computing something twice
import re
# Without walrus: compute len(s) twice
long_strings = [s for s in ["hi", "hello", "hey", "howdy"] if len(s) > 3]
# With walrus: compute len(s) once, reuse it
results = [(s, length) for s in ["hi", "hello", "hey", "howdy"] if (length := len(s)) > 3]
print(results) # [('hello', 5), ('howdy', 5)]
# Practical: filter and transform with regex
texts = ["Price: $42", "No price", "Price: $99", "N/A"]
prices = [
int(m.group(1))
for text in texts
if (m := re.search(r'\$(\d+)', text))
]
print(prices) # [42, 99]
When to Use Comprehensions
- Simple transformations: Mapping, filtering, or combining in one step
- Keep it readable: If a comprehension spans more than 2 lines, use a regular loop
- No side effects: Comprehensions should create values, not perform actions
- Use generators for large data: Replace [] with () if you do not need the full list