1.3.10 · D3Python Intermediate

Worked examples — Iterators — `__iter__`, `__next__`, StopIteration

2,744 words12 min readBack to topic

The scenario matrix

Every problem about iterators falls into one of these cells. Each row is a "case class"; the last column names the worked example that covers it.

Cell Situation The tricky part Covered by
A Finite iterator, counts down exhaustion check ordering Ex 1
B Finite iterator, counts up to a bound when to raise vs return Ex 2
C Empty input (degenerate) StopIteration on the first press Ex 3
D Infinite iterator never raising; how to stop it safely Ex 4
E Consumed-once bug (iterator IS itself) state not resetting Ex 5
F Reusable iterable (fresh iterator each loop) __iter__ returns a new object Ex 5
G Manual driving with next(it, default) default suppresses the raise Ex 6
H Nested loops over one list two independent positions Ex 7
I Real-world word problem (streaming / lazy) memory, one item at a time Ex 8
J Exam twist: StopIteration inside a generator (PEP 479) why it becomes RuntimeError Ex 9

We now clear the whole board, cell by cell.


Ex 1 — Cell A: finite count-down

Figure — Iterators — `__iter__`, `__next__`, StopIteration

Ex 2 — Cell B: finite count-up to a bound


Ex 3 — Cell C: the degenerate empty case


Ex 4 — Cell D: an infinite iterator, stopped safely


Ex 5 — Cells E & F: consumed-once vs reusable

Figure — Iterators — `__iter__`, `__next__`, StopIteration

Ex 6 — Cell G: manual driving with a default


Ex 7 — Cell H: nested loops share a list, not a position


Ex 8 — Cell I: real-world word problem (lazy streaming)


Ex 9 — Cell J: the exam twist (PEP 479)


Recall One-line summary of the whole board

Finite → check-then-return; empty → check fires first press; infinite → never raise, bound with islice; consumed-once → return a fresh iterator from __iter__; nested loops → each iter() is independent; generators → return, never raise.

Exhaustion count fact
Looping over items presses the button times (the extra press raises StopIteration).
Why is list(Evens()) dangerous
It never raises StopIteration, so the list keeps growing forever — bound it with islice.
Why does the second loop over a self-iterator give []
The object is its own iterator; its state was consumed and never reset.
What ends a generator vs a hand-written iterator
Generator uses return; hand-written __next__ uses raise StopIteration.

Connections

  • Iterators — `__iter__`, `__next__`, StopIteration — the parent protocol these examples exercise.
  • itertools — islice, count, chain — the safe way to bound infinite iterators (Ex 4).
  • Generators — yield, lazy evaluation — Ex 9's context; return vs raise.
  • for loops and comprehensions — every example is really iter + next + catch.
  • Lazy evaluation and memory efficiency — the WHY behind Ex 4 and Ex 8.
  • StopIteration and PEP 479 — the rule Ex 9 tests.
  • Dunder (magic) methods__iter__/__next__ live here.