Iterators, this name might be new for most of us, but What if I tell you that you have already used this within for loops, comprehensions etc. So, in this blog, let’s see what are iterators, how they work and how we can build our own iterator.
What is an iterator and how it works?
To understand this, we first need to know what is an iterable
Iterable: It is anything that you are able to loop over like lists, tuples, strings etc.
Iterator: It is the object that does the actual iterating.
So, in order to iterate, you must first convert an iterable into an iterator. This is done by using built-in iter() function.
1 2 3 4 |
>>> my_list = [1,2,3,4] >>> iter_obj = iter(my_list) >>> iter_obj <list_iterator object at 0x000000E7431745F8> |
To get the next element, use built-in next() function on that iterator. next() function raises a StopIteration exception when there are no more elements in that iterator.
1 2 3 4 |
>>> next(iter_obj) 1 >>> next(iter_obj) 2 |
Note: If we directly apply next() on iterable like lists etc. it will give a typeerror as
1 2 3 4 5 |
>>> next(my_list) Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> next(my_list) TypeError: 'list' object is not an iterator |
Thus, __iter__() and __ next__() (called the iterator protocol)are the two special methods implemented by the iterator.
Pros: Iterators are lazy, meaning, they don’t determine what their next item is until you ask them for it. This saves memory, time and can work with infinite sequences.
Building our own iterator:
To build an iterator, we only need the methods __iter__() and __next__(). Below, we show an example that will give us the next Fibonacci term in each iteration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Fib: def __init__(self, max = 0): self.max = max self.a = 0 self.b = 1 self.n = 0 def __iter__(self): return self def __next__(self): if self.n <= self.max: result = self.a + self.b self.a,self.b=self.b,result self.n+=1 return result else: raise StopIteration |
Now we can create an iterator and iterate through it as follows.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
>>> a = Fib(3) >>> next(a) 1 >>> next(a) 2 >>> next(a) 3 >>> next(a) 5 >>> next(a) Traceback (most recent call last): File "<pyshell#6>", line 1, in <module> next(a) File "C:\New folder\pp.py", line 19, in __next__ raise StopIteration StopIteration |
Here, I haven’t called the iter() method because it returns the object itself. You may call this, as this will not affect anything.
We can also use for loop to iterate over our Fib Class as:
1 2 3 4 5 6 7 |
>>> for i in Fib(3): print(i) 1 2 3 5 |
Here, for loop doesn’t give stopiteration exception because it uses try-except statement(See here how the for loop works)
Now, you might have got some feeling about the Python iterators and iterable. Hope you enjoy reading.
If you have any doubt/suggestion please feel free to ask and I will do my best to help or improve myself. Good-bye until next time.