In Python, iterators are an essential concept that allows you to traverse through all elements of a collection one by one. To create an iterator, two special methods, __iter__()
and __next__()
, play a central role. In this article, we will explore these methods, how they work, and how to implement them in your own custom iterators.
An iterator is any object in Python that implements two specific methods:
StopIteration
exception to signal the end of the iteration.The __iter__()
method is used to initialize the iterator. It is required in any class that is to be considered an iterator. This method must return the iterator object itself.
class MyIterator: def __init__(self, start, end): self.current = start self.end = end def __iter__(self): return self def __next__(self): if self.current <= self.end: self.current += 1 return self.current - 1 else: raise StopIteration # Using the custom iterator my_iter = MyIterator(1, 5) for number in my_iter: print(number)
In this example, the class MyIterator
defines the __iter__()
method, which simply returns the iterator object itself (in this case, self
). This is essential for the object to be used in a loop or other iterating mechanisms in Python.
1 2 3 4 5
The __next__()
method is responsible for returning the next value from the iterator. Once all the values are exhausted, the method must raise a StopIteration
exception to signal that the iteration is complete.
class MyIterator: def __init__(self, start, end): self.current = start self.end = end def __iter__(self): return self def __next__(self): if self.current <= self.end: self.current += 1 return self.current - 1 else: raise StopIteration # Using the custom iterator my_iter = MyIterator(1, 3) print(next(my_iter)) # Output: 1 print(next(my_iter)) # Output: 2 print(next(my_iter)) # Output: 3 print(next(my_iter)) # Raises StopIteration
Here, we use the next()
function to retrieve values from the iterator. When all values are exhausted, the StopIteration
exception is raised to indicate the end of the iteration.
1 2 3 StopIteration
Python provides built-in support for iterators with collections like lists, tuples, and dictionaries. These objects already implement the __iter__()
and __next__()
methods, so you can iterate through them directly.
numbers = [10, 20, 30] numbers_iter = iter(numbers) print(next(numbers_iter)) # Output: 10 print(next(numbers_iter)) # Output: 20 print(next(numbers_iter)) # Output: 30
Here, we use the iter()
function to create an iterator from a list. The next()
function retrieves the next value from the list until all values are exhausted, at which point it raises a StopIteration
exception.
10 20 30
By implementing __iter__()
and __next__()
, you can create custom iterators for any collection or range of values that fits your needs.
class FibonacciIterator: def __init__(self, limit): self.limit = limit self.a, self.b = 0, 1 def __iter__(self): return self def __next__(self): if self.a > self.limit: raise StopIteration a, self.a, self.b = self.a, self.b, self.a + self.b return a # Using the Fibonacci iterator fib_iter = FibonacciIterator(10) for num in fib_iter: print(num)
In this example, the FibonacciIterator
generates the Fibonacci sequence up to a specified limit. The __next__()
method calculates the next Fibonacci number and raises a StopIteration
exception when the limit is exceeded.
0 1 1 2 3 5 8
Understanding the __iter__()
and __next__()
methods is essential for creating custom iterators in Python. These methods allow you to define how your objects behave when they are used in loops or any context where iteration is required. By implementing these methods, you can create flexible, memory-efficient iterators that suit your needs, whether you're working with numbers, sequences, or custom collections.