This is a parent topic deep dive. Here we don't
teach the syntax from scratch — the parent did that. Instead we hunt down every kind of situation
comprehensions and generators can throw at you, and we work each one to the ground. If you have not
yet met the words iterable, yield, or lazy evaluation, read the parent note first, then come
back.
Every worked example below is tagged with a cell code (e.g. [C3]) so you can see the box being ticked.
Cell
Case class
The tricky part it stresses
C1
Plain map (transform only)
Baseline: expression per item
C2
Map + filter (if clause)
Order: filter then transform
C3
Two iterables via zip → dict
Pairing keys with values
C4
Nested / flatten
Left-to-right reading of nested for
C5
Empty / degenerate input
Empty iterable → empty result, no crash
C6
Generator exhaustion
Consumed-once behaviour
C7
Infinite / limiting stream
Lazy yield lets n→∞ work
C8
Memory word-problem (real ML)
List vs generator on a huge file
C9
Conditional expression (if…else in the expression)
Different placement of if
C10
Exam twist — side-effect trap
Purity, iterator invalidation
We now walk C1 → C10. Guess each answer before reading the steps.
Recall Self-test: name the cell for each snippet
[len(w) for w in words] hits which cell? ::: C1 (plain map)
(x for x in range(9)); list(that); list(that) demonstrates which cell? ::: C6 (exhaustion)
["hi" if x else "lo" for x in flags] is which cell? ::: C9 (ternary in the expression)
Reading [c for row in grid for c in row] left-to-right is which cell? ::: C4 (nested flatten)
Streaming a 10 GB file with (...) instead of [...] is which cell? ::: C8 (memory word problem)
Recall One-line summary
Front if…else chooses a value; back if filters; zip pairs; nested for reads outer→inner;
generators are single-use lazy straws; empty inputs give empty outputs, never crashes.