Generators vs Iterators: When to Use Each in Python
Understand the key differences between Python generators and iterators, with practical guidance on when to use each for cleaner code and better memory efficiency.
You've probably heard both terms thrown around in Python circles, and maybe you've even used them without realizing it. But when you're sitting down to write code for PythonSkillset, knowing the difference between generators and iterators can save you memory, time, and a headache or two.
Let's clear the air first: every generator is an iterator, but not every iterator is a generator. That's the short version. The long version is where things get interesting.
What Makes an Iterator?
An iterator is any object that follows the iterator protocol. In plain English, that means it has two methods: __iter__() and __next__(). When you call next() on it, it returns the next item until there's nothing left, then raises StopIteration.
Think of it like a playlist on your phone. You hit "next track," and it plays the song. When the playlist ends, it stops. Simple.
Here's a basic custom iterator:
class CountDown:
def __init__(self, start):
self.current = start
def __iter__(self):
return self
def __next__(self):
if self.current <= 0:
raise StopIteration
num = self.current
self.current -= 1
return num
You'd use it like this:
for number in CountDown(5):
print(number) # 5, 4, 3, 2, 1
What Makes a Generator Different?
A generator is just a function that uses yield instead of return. When Python sees yield, it knows to create a generator object. The magic is that the function pauses at each yield and resumes when you ask for the next value.
The same countdown as a generator:
def count_down(start):
while start > 0:
yield start
start -= 1
That's it. No class, no __next__ method, no StopIteration handling. Python does all that work for you.
So When Should You Use Each?
This is where most tutorials go wrong. They tell you "generators are easier" and leave it at that. But the real answer depends on what you're building.
Use generators when: - You need a quick, one-off sequence without writing a full class - Your sequence is infinite or extremely large (like reading a 10GB log file) - You want lazy evaluation — values computed only when needed
Use custom iterators when: - You need to maintain complex state between iterations - Your object has multiple ways to be iterated over - You're building a library where clarity matters more than brevity
I ran into this while building a data pipeline for PythonSkillset's analytics dashboard. For processing server logs line by line, a generator made perfect sense. But for a custom tree structure that needed to be traversed in three different orders, writing a proper iterator class was the cleaner choice.
The Memory Question
Here's a concrete example. Say you need to process the first 10 million square numbers. Using a list:
squares = [x**2 for x in range(10_000_000)] # This eats about 400MB of RAM
Using a generator expression:
squares = (x**2 for x in range(10_000_000)) # This uses almost no memory
That's not a small difference. That's the difference between your app running smoothly and your server swapping like crazy.
Watch Out for One Thing
Generators are single-use. Once you've consumed them, they're gone. If you need to loop over the same data twice, store it or use an iterator that supports resetting.
gen = (x for x in range(3))
list(gen) # [0, 1, 2]
list(gen) # [] - empty!
A custom iterator could easily add a reset method. A generator cannot.
The Bottom Line
Start with generators. They're simpler, memory-efficient, and cover 90% of cases where you'd want iteration with laziness. But when you find yourself fighting against the generator's stateless nature or needing multiple traversal strategies, don't hesitate to reach for a proper iterator class.
PythonSkillset readers often ask me "should I learn both?" The answer is yes, but learn generators first. They'll make your code cleaner and your programs faster. Then, when you encounter that 10% case that demands something more powerful, you'll know exactly what to reach for.
Comments
Questions, corrections, and tips stay visible for everyone reading this page.
Join the discussion
No comments yet
Be the first to leave a note — it helps the next reader.