How to build a basic iterator?
iterator, object, python
Solution
Iterator objects in python conform to the iterator protocol, which basically means they provide two methods: `__iter__()` and `__next__()`.
The `__iter__` returns the iterator object and is implicitly called at the start of loops.
The `__next__()` method returns the next value and is implicitly called at each loop increment. This method raises a StopIteration exception when there are no more value to return, which is implicitly captured by looping constructs to stop iterating.
Here's a simple example of a counter:
class Counter:
def __init__(self, low, high):
self.current = low - 1
self.high = high
def __iter__(self):
return self
def __next__(self): # Python 2: def next(self)
self.current += 1
if self.current < self.high:
return self.current
raise StopIteration
for c in Counter(3, 9):
print(c)
This will print:
3
4
5
6
7
8
This is easier to write using a generator, as covered in a previous answer:
def counter(low, high):
current = low
while current < high:
yield current
current += 1
for c in counter(3, 9):
print(c)
The printed output will be the same. Under the hood, the generator object supports the iterator protocol and does something roughly similar to the class Counter.
David Mertz's article, Iterators and Simple Generators, is a pretty good introduction.
Problem
How can I create an iterator in Python? For example, suppose I have a class whose instances logically "contain" some values: ``` class Example: def __init__(self, values): self.values = values ``` I want to be able to write code like: ``` e = Example([1, 2, 3]) # Each time through the loop, expose one of the values from e.values for value in e: print("The example object contains", value) ``` More generally, the iterator should be able to control where the values come from, or even compute them on the fly (rather than considering any particular attribute of the instance).