An iterator is an object that allows for the traversal of datasets that can be sequentially indexed. Iterators generally use lazy computation so that its ranges of elements are not necessarily stored in memory but rather obtained from computation when necessary. Iterators also have a next component to get the next item in the dataset series and have a means to stop iteration if there are no more elements to be computed. Because elements in a series are lazily computed by an iterator, the iterator is a mutable object that only keeps track of its current position as it advances through the series.
In Python, iterators have built-in interfaces that form the iterator protocol. An iterator is an object with both a __next__ method that returns the next sequential value or stops iteration upon ending and a __iter__() method that returns itself (the iterator object is self-iterable).
Here is an example of an iterator that iterates over a decreasing series of integers from start to end. When the next() method returns its last value and the number it currently tracks is less than end, then it will raise a StopIteration exception that can then be handled.
>>> class Countdown: def __init__(self, start=3, end=0): self.next_num = start self.end = end def __next__(self): if self.next_num < self.end: raise StopIteration num = self.next_num self.next_num -= 1 return num def __iter__(self): return self >>> count_iter = Countdown() >>> count_iter.__next__() 3 >>> next(count_iter) 2 >>> count_iter.__next__() 1 >>> next(count_iter) 0 >>> count_iter.__next__() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 6, in __next__ StopIteration
This FibIter class, which uses an iterative algorithm to compute the next number in the Fibonacci sequence, is an example of an iterator that represents an infinite dataset. The StopIteration exception is never called as there will always be further items.
>>> class FibIter: def __init__(self): self.curr = 0 self.next = 1 def __next__(self): num = self.curr self.curr, self.next = self.next, self.curr + self.next return num def __iter__(self): return self >>> fib_iter = FibIter() >>> fib_iter.__next__() 0 >>> next(fib_iter) 1 >>> fib_iter.__next__() 1 >>> next(fib_iter) 2