Python Iterators
Table of Contents
In the last lesson, we learned about the Python pip Package Manager. Now let us learn how iterators return values one at a time.
What Is an Iterator in Python?
An iterator is an object that implements two methods: __iter__ and __next__. The __iter__ method returns the iterator object itself. The __next__ method returns the next value in the sequence. When there are no more values, it raises a StopIteration exception.
Think of an iterator like a bookmark in a book. It remembers where we are. Each time we ask for the next item, it gives us the next one and moves the bookmark forward.
Why Do We Need Iterators in Python?
Iterators are everywhere in Python. The for loop uses them behind the scenes. Lists, tuples, dictionaries, and strings are all iterable. They can be looped over because they have an iterator.
Iterators let us work with large data sets without loading everything into memory at once. They produce values one at a time, on demand.
How to Use an Iterator in Python
We can get an iterator from any iterable using the iter() function. Then we use next() to get values one by one.
numbers = [1, 2, 3]iterator = iter(numbers)
print(next(iterator))print(next(iterator))print(next(iterator))Output
123If we call next() again, we get a StopIteration exception.
print(next(iterator))Output
StopIterationThat is how a for loop works internally. It calls iter() to get an iterator, then calls next() repeatedly until StopIteration is raised.
How to Create a Custom Iterator in Python
We can create our own iterator by defining a class with __iter__ and __next__ methods.
Let us create an iterator that counts from 1 to a given limit.
class Counter: def __init__(self, limit): self.limit = limit self.current = 1
def __iter__(self): return self
def __next__(self): if self.current > self.limit: raise StopIteration value = self.current self.current += 1 return value
counter = Counter(3)
for num in counter: print(num)Output
123The __iter__ method returns self. The __next__ method returns the next value and raises StopIteration when done.
A Real-Life Example – Fibonacci Iterator
Let us create an iterator that generates Fibonacci numbers.
class Fibonacci: def __init__(self, limit): self.limit = limit self.a = 0 self.b = 1 self.count = 0
def __iter__(self): return self
def __next__(self): if self.count >= self.limit: raise StopIteration value = self.a self.a, self.b = self.b, self.a + self.b self.count += 1 return value
fib = Fibonacci(5)
for num in fib: print(num)Output
01123That is a useful iterator for generating sequences.
Common Mistakes with Iterators in Python
Mistake 1: Forgetting to raise StopIteration
class Counter: def __init__(self, limit): self.limit = limit self.current = 1
def __iter__(self): return self
def __next__(self): value = self.current self.current += 1 return valueThis iterator never stops. The for loop will run forever.
Fix: Raise StopIteration when the sequence ends.
def __next__(self): if self.current > self.limit: raise StopIteration value = self.current self.current += 1 return valueMistake 2: Returning a value from iter that is not self
def __iter__(self): return [1, 2, 3]This works for some cases, but it is not a proper iterator. The object returned must have a __next__ method.
Fix: Return self and implement __next__.
Mistake 3: Using an iterator after it is exhausted
iterator = iter([1, 2, 3])for x in iterator: print(x)for x in iterator: print(x)The second loop prints nothing. Because the iterator is exhausted.
Fix: Create a new iterator if you need to loop again.
Next, we will learn about Python Generators and create iterators more easily with yield.