As noted here iterator objects are required to implement both __iter__
and __next__
methods.
The iterator objects themselves are required to support the following two methods, which together form the iterator protocol:
iterator.__iter__()
Return the iterator object itself. This is required to allow both containers and iterators to be used with the for and in statements. This method corresponds to the tp_iter slot of the type structure for Python objects in the Python/C API.
iterator.__next__()
Return the next item from the iterator. If there are no further items, raise the StopIteration exception. This method corresponds to the tp_iternext slot of the type structure for Python objects in the Python/C API.
By this definition in the below snippet, I didn't have implemented an iterator:
class Test:
def __init__(self, size):
self.size = size
def __iter__(self):
return TestIter(self.size)
class TestIter:
def __init__(self, target=20):
self.counter = 0
self.target = target
def __next__(self):
if self.counter > self.target:
raise StopIteration
self.counter += 1
return self.counter
Because neither Test
nor TestIter
has both __iter__
and __next__
methods defined. But the Test
class has fully functionality of an iterator.
>>> for i in Test(5):
... print(i)
...
1
2
3
4
5
6
>>>
>>> list(Test(5))
[1, 2, 3, 4, 5, 6]
>>>
>>> it = iter(Test(5))
>>> next(it)
1
>>> next(it)
2
>>> next(it)
3
>>> next(it)
4
>>> next(it)
5
>>> next(it)
6
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/tmp/iterators.py", line 18, in __next__
raise StopIteration
StopIteration
>>>
Is this technically correct that Test
is not an iterator according to the definition?