Comprehensions, Iterators & Generators
List Comprehensions
Build a list from an iterable in one expression — Python’s signature move:
nums = [1, 2, 3, 4, 5, 6]
squares = [n ** 2 for n in nums]
# [1, 4, 9, 16, 25, 36]
evens = [n for n in nums if n % 2 == 0] # with a filter
# [2, 4, 6]
labels = [f"#{n}" for n in nums if n > 3]
# ['#4', '#5', '#6']Read it as: “collect f(n) for each n in nums if condition”. One filter and one transform is the sweet spot — beyond that, use a regular loop for readability.
Dict & Set Comprehensions
users = ["Ravi", "Asha", "Dev"]
lengths = {name: len(name) for name in users}
# {'Ravi': 4, 'Asha': 4, 'Dev': 3}
initials = {name[0] for name in users} # a set
# {'R', 'A', 'D'}
# invert a dict
by_id = {1: "ravi", 2: "asha"}
by_name = {v: k for k, v in by_id.items()}The Iterator Protocol
A for loop calls iter() on your object, then next() repeatedly until StopIteration. Anything implementing that is iterable — lists, strings, files, dict views, generators. That’s why one loop syntax works everywhere.
Generators — Lazy Sequences
A function with yield returns a generator: it produces values one at a time, on demand, remembering where it left off. Nothing is computed until you ask:
def countdown(n):
while n > 0:
yield n
n -= 1
for x in countdown(3):
print(x) # 3, 2, 1The killer use case is large data — process a 10 GB log file with constant memory:
def error_lines(path):
with open(path, encoding="utf-8") as f:
for line in f: # files are already lazy
if "ERROR" in line:
yield line.rstrip()
for line in error_lines("app.log"):
print(line) # never loads the whole fileGenerator Expressions
A comprehension with parentheses — lazy instead of building a list:
total = sum(n ** 2 for n in range(1_000_000)) # no million-item list created
has_admin = any(u.is_admin for u in users) # stops at the first TruePipelines
Generators compose into streaming pipelines — each stage pulls from the previous one, one item at a time:
lines = (l.strip() for l in open("data.csv", encoding="utf-8"))
rows = (l.split(",") for l in lines if l)
scores = (int(r[1]) for r in rows)
print(max(scores))