Iterators: Python’s Waiters with One-Way Memory 🍴🤖

Full-Stack Developer & Tech Writer specializing in Python (Django, FastAPI, Flask) and JavaScript (React, Next.js, Node.js). I build fast, scalable web apps and share practical insights on backend architecture, frontend performance, APIs, and Web3 integration. Available for freelance and remote roles.
Welcome back, hungry coder! In Part 1 we walked around the Python buffet, exploring iterables the giant table full of delicious data dishes.
But here’s the truth: you don’t eat from the buffet directly. You need a waiter. Someone to serve you one bite at a time. Enter the iterator the hardworking waiter who remembers exactly where they left off, but (spoiler alert) has terrible memory once they’re done.
This post mixes fun metaphors with a serious deep dive into Python internals. Let’s pull back the curtain.
🍱 Buffet vs Waiter
Iterable (buffet table) → has all the food laid out. You can ask for a fresh waiter at any time.
Iterator (the waiter) → carries the plate, remembers where they stopped, but can only go forward.
👉 Rule of thumb: Buffets can be visited again and again. Waiters, once they’ve served all the food, clock out permanently.
🔧 What Makes an Iterator?
In Python, an iterator is just an object that:
Implements
__iter__()→ usually just returns itself.Implements
__next__()→ gives the next item, or says “I’m out!” by raisingStopIteration.
Example:
nums = [1, 2, 3]
it = iter(nums)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
print(next(it)) # StopIteration 🚫
That’s the life of a waiter: step by step, until nothing’s left.
🧬 Behind the Scenes What’s in Memory?
When you create an iterator from a list, Python doesn’t duplicate the list. Instead:
It stores a reference to the original list.
It keeps a cursor (an index).
It may store some safety bits (like mutation checks in CPython).
That’s it.
➡️ Iterators are cheap and tiny. That’s why they’re great for streaming data without ballooning memory.
🚪 Why No Rewind?
Because an iterator doesn’t log history. It only tracks the current position.
If you need to restart, you must go back to the buffet (iterable) and ask for a brand-new waiter.
😵 Classic Oops Moment
it = iter([1, 2, 3, 4])
print(sum(it)) # → 10 (all consumed)
print(list(it)) # → [] (oops, empty!)
Once one consumer finishes the waiter, the next one gets scraps.
👉 Fix: share the iterable, not the iterator. Or, if you need multiple passes, turn it into a list first.
🛠️ Build Your Own Iterator
Here’s how you’d roll your own waiter:
class Counter:
def __init__(self, limit):
self.limit = limit
self.current = 0
def __iter__(self):
return self # it’s its own waiter
def __next__(self):
if self.current >= self.limit:
raise StopIteration
self.current += 1
return self.current
Using it:
for n in Counter(3):
print(n)
Output:
1
2
3
Cute little waiter, isn’t it?
🎲 Fun Extras You Didn’t Know
iter(callable, sentinel)trickimport random dice = iter(lambda: random.randint(1, 6), 6) for roll in dice: print(roll) # stops once we roll a 6Like a game of dice infinite until the magic number shows up.
Infinite waiters
itertools.count()is a waiter that never runs out. Infinite breadsticks, anyone? 🍞
(Just don’t loop forever by accident.)Lazy pipelines
You can daisy-chain iterators withmap,filter,itertools.chain, etc.
That’s how you process giant datasets without eating all your RAM.
⚔️ Memory Battle: Lists vs Iterators vs Generators
List → prepares the entire feast ahead of time. Huge memory bill.
Iterator → serves one item at a time, cheap but one-way.
Generator → basically a custom iterator you write with
yield.
➡️ Use lists when you need to revisit items often.
➡️ Use iterators/generators when you just want to munch once and move on.
🖼️ Visual Recap
Iterable (Buffet) → __iter__ → Iterator (Waiter)
Iterator → __next__ → Next dish or StopIteration
One-way memory. One-way trip.
✅ Wrap-Up
In this part we explored:
How Python waiters (iterators) actually work.
Why they’re light in memory but one-way only.
Common mistakes when sharing iterators.
How to craft your own waiter class.
Fun tricks (
iter(callable, sentinel), infinite iterators, pipelines).
👉 Next: Part 3 Generators: Lazy Magicians of Python 🎩🐍
We’ll open the magic box of yield, peek into generator frames, and see how they power async/await.



