Creating Custom Iterators
00:00
Based on what you learned in the last lesson, you need two magic methods to create your own custom iterators. Calling the __iter__
magic method initializes the iterator and must return and iterator object, usually the iterator itself and calling the __next__
magic method iterates over the iterator and must return the next value in the data stream.
00:26 This convention is called the Iterator Protocol.
00:30 Let’s get practical and create a class that provides an iterator over the numbers in the Fibonacci sequence. Just as a reminder, the Fibonacci sequence is a series of numbers where each number is the sum of the two proceeding ones starting from zero and one. So it goes like 0 1, then zero plus one is one, so it becomes 0 1 1.
00:53 The next number in the sequence is one plus one, which is 2, and so on.
01:01
Let’s start by defining the FibonacciIterator
class.
01:06
Now you have to set up the __init__
magic method here you need to set up the initial two Fibonacci numbers, zero and one, and also keep track of how many numbers have been generated so far.
01:18
You’ll include a max_count
parameter to limit the number of iterations. So you need a self.current
and also a self.next
.
01:29
Now there are just zero and one, and you also need to set up your max_count
self
.max_count
equal to the max_count
that you’ll get when you instantiate the FibonacciIterator
class.
01:46
You also need a self.count
. This keeps track of how many Fibonacci numbers have been produced so far. It has to do with the StopIteration
exception error message you learned about in the last lesson and starts from zero.
02:05
That’s the __init__
magic method initialization. Now, you need to make your class an iterator. You need to follow the iterator protocol, so you need an __iter__
magic method.
02:18
So def __iter__(self):
The __iter__
method returns the iterator object itself, which is necessary for making the class an iterable.
02:32
The next magic method you need to implement is the __next__
magic method. You’ll define how the Fibonacci numbers will be generated here one by one while also respecting the max_
count
limit that you set earlier.
02:48
So def __next__(self):
Here if max_count
is set and the number of generated Fibonacci numbers has reached this limit, the iterator should raise the StopIteration
exception signaling that, hey, there are no more items for me to produce.
03:11
So if self.max_count
is not None
, and also self.count
is bigger or equal to self.max_count
, you need to raise StopIteration
. Now, before you actually replace the current Fibonacci number with the next one, you need to store it in a variable.
03:38
Let’s name it value = self.current
.
03:43
And now you can advance the sequence by updating self.current
and self.next
will be equal to so the current one would be advancing to the next one.
03:54
So self.next
and self.next
will become self.current
plus self.next
.
04:04
And don’t forget that you have to add one to the current count number. So self.count
, whatever it is now, it should be plus one. Okay, perfect. Now you can actually return value
variable here, which is the next number in the sequence.
04:24
Okay, perfect. You did a lot here so let’s recap. In the __next__
magic method the current Fibonacci number is stored in value and then the sequence is advanced by updating self.current
and self.next
. The self.count
variable keeps track of how many numbers have been generated so far, and finally, you’re returning value
, which gives you the next number in the sequence, and that’s it.
04:51
You just created a custom iterator by following the Iterator protocol, meaning you implemented the __iter__
and __next__
magic methods here.
05:02
Now you can use this class to create an iterator that generates a specific number of a Fibonacci numbers and you can use the next()
built-in function to retrieve them.
05:14
Let’s go ahead and do exactly that. So let’s create an iterator that provides the first ten Fibonacci numbers. First, you need to create an instance, let’s call it fib_iterator
equal to the FibonacciIterator
, and the max_count
should be equal to 10.
05:38
Now here you can call next()
on fib_iterator
multiple times by hand, or you can just use a for
loop to do that. So we’re gonna be doing the for
loop option.
05:49
Let’s say for i in range(10): print(
next(fib_iterator))`.
06:02 Okay, let’s see if this works.
06:08
And it does. We have 0 1, 1, 2, 3, 5, 8, 13, 21, and 34, which is the correct sequence. So it works. Now to make sure that everything works, let’s also check the StopIteration
exception that you created earlier.
06:28
So after the for
loop, let’s again use the next()
function on fib_iterator
. So let’s do that. print(next(fib_iterator))
06:41
Let’s see what happens now. And indeed, you get the sequence until 34, and then you get a StopIteration
exception. It works.
Become a Member to join the conversation.