An iterator is an object that:
✔ Produces values one at a time
✔ Keeps track of iteration state
✔ Implements special methods
Core idea:
Iterator = Stateful Value Producer
Python iteration works like this:
Iterable → Iterator → next() → Value
Very important distinction.
| Concept | Meaning |
|---|---|
| Iterable | Object you can loop over |
| Iterator | Object that produces values |
Example:
my_list = [1, 2, 3]
✔ List = Iterable
❌ List ≠ Iterator
numbers = [1, 2, 3]
iterator = iter(numbers)
print(iterator)
Output:
<list_iterator object at 0x...>
✔ Now we have an iterator.
print(next(iterator))
print(next(iterator))
print(next(iterator))
Output:
1
2
3
✔ Iterator advances each time.
next(iterator) → iterator.__next__()
Python simply calls:
__next__()
Behind the scenes.
print(next(iterator))
ERROR:
StopIteration
✔ Means no more values.
✔ Memory efficient
✔ Lazy evaluation
✔ Used by loops
✔ Used by generators
✔ Used by files
✔ Used by large datasets
Core of Python efficiency.
Any iterator must implement:
✔ iter()
✔ next()
This is Python’s contract.
Let’s build Python iteration manually.
Example:
class Counter:
def __init__(self, max):
self.max = max
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max:
raise StopIteration
self.current += 1
return self.current
counter = Counter(3)
print(next(counter))
print(next(counter))
print(next(counter))
Output:
1
2
3
✔ Manual iteration engine.
next(counter)
→ Calls __next__()
→ Returns value
→ Saves state
→ Advances pointer
Iterator remembers progress.
| Feature | Iterator | Generator |
|---|---|---|
| Implementation | Manual class | Function with yield |
| State Handling | Manual | Automatic |
| Complexity | Higher | Lower |
| Memory Efficient | Yes | Yes |
Generator = Shortcut Iterator
def generator():
yield 1
yield 2
✔ Generator automatically implements:
✔ iter()
✔ next()
✔ for loops
✔ Generators
✔ File objects
✔ range()
✔ map()
✔ filter()
✔ zip()
✔ enumerate()
Everywhere.
Hidden Truth
for loop internally does:
iterator = iter(iterable)
while True:
try:
value = next(iterator)
except StopIteration:
break
Loop mechanics revealed.
next([1, 2, 3]) # ERROR
✔ Must call iter() first.
Once consumed → Gone forever.
Iterator ≠ Indexable.
Each iterator maintains its own state.
Possible → Must control carefully.
Custom iterator must raise StopIteration.
Iterators enable:
✔ Lazy evaluation
✔ Streaming systems
✔ Infinite sequences
✔ Memory-safe iteration
✔ Pipeline processing
✔ Core Python internals
Fundamental concept.
✔ Complex iteration logic
✔ Controlled state machines
✔ Infinite sequences
✔ Lazy pipelines
Rare for simple tasks.
✔ Prefer generators (simpler)
✔ Use iter() properly
✔ Handle exhaustion safely
✔ Raise StopIteration correctly
✔ Avoid unnecessary manual iterators
✔ Iterator = Stateful value producer
✔ Created via iter()
✔ Consumed via next()
✔ Implements iterator protocol
✔ StopIteration signals end
✔ Core of Python loops
✔ Generators = Iterator shortcut
- Convert list to iterator
- Use next() manually
- Trigger StopIteration
- Use default fallback
- Build custom iterator
- Implement iterator protocol
- Create infinite iterator
- Compare generator vs iterator