Welcome back.
I want us to understand how things work underneath the hood.
So I'm going to show you two examples of implementing our own for loop and then implementing our own
range function.
So the first one is our for loop.
So I'm going to say special for loop.
Underneath the hood, all it's doing is receiving an iterable.
And then we're going to say iterator.
Is going to equal an iterable now for us to have an iterable.
We have what we call an inner function.
That accepts the iterable we just passed.
Now this intervention is going to allow us to use the next function on this iterable.
So stay with me.
I'm going to say while true.
I want to try.
And in this tribe block we'll say iterator.
And we can perform, let's say, some sort of operation here if we want.
Or we can just call next iterator.
You know what?
Let's print something here, just so we see what the iterator is.
And then finally I want us to stop when we have the stop iteration exception.
Remember the one that we saw where there's no more items in the Iterable?
And here we simply can just break.
Go and make sure that.
I have the Colin set correctly.
So now if I do a special for loop and give it a list of one, two, three and I click Run.
Check it out.
I loop through some iterable objects using next.
And you see that this object exists in the same memory space, even though we're constantly looping
through it through 1 to 3.
So this is how four loops work underneath the hood when we do for let's say NUM and then give it a list.
It's going to go through everything.
It's going to turn it into an iterable and it's going to keep running and keep calling next iterator
on it over and over and over until we finish the end of the line and then break out of the loop.
And how do we check the actual values of the iterator?
Well, remember, the next function is going to output whatever the item is next.
So if I do print here.
And I click Run.
I get.
One, two, three.
So I can just do times two if I wanted to click Run.
And there you go.
Our special for Loop just multiplied our list by two.
That's it.
That's how for loops really work.
But what about ranges?
Can we create our own range function?
We absolutely can.
And this is a fun one.
Let's create a class and this class because at the end of the day, we're just going to create an object.
That has actions that we can do.
So I'll say my gen for my generator and this is going to mimic what our range does.
So I'm going to have a class and this class will have a init function.
We'll have a self, a first and last.
So this is how a range we're able to say, start with this and end with this.
And in here we'll do the typical self dot first.
Equals to first.
And then self dott last equals to last.
And I'm using a class here because remember we're just creating our own data type, our own special
range in Python.
Now we have our sample generator and ideally we want to be able to say gen equals and instantiate my
gen to have, let's say 0 to 100 just like we would with a range.
And ideally we can say for AI and gen.
And print.
I because I mean, that's how we're able to use ranges, right?
So how can I make this work?
Well, we can use our dunder methods.
So remember how we have the eter.
To get an iterator and use next on them.
Well we have a define dunder that is emitter and emitter allows us to create.
An arable.
So in our case I'll say self and here I'm just going to return the actual class like so.
And then finally we want to be able to run the next function on our Jen because we saw how four loops
work.
We need to be able to use the itor and then the next M&M.
So once again, we can use a dunder method, which is conveniently called.
Next.
And this is built into Python.
So if I do here self.
And all we want to do here is to let it know how we want next to work.
Well, I'll say if.
And we need some sort of state or data to keep track of where we are.
Remember how generator functions.
Remember where they are.
Well, we can create a class object attribute.
So I can say current equals to zero.
So this is where we are currently on our iteration and say my gen dot current.
As long as that is less than self dot last, which will be the 100 here.
If that's the case.
Well, I want a number to equal my gen dot current.
I want to increase my gen dot current by one because we want to say, hey, we're moving up to the next
location and then return.
The number.
Because that's how next works underneath the hood, right?
We increment our current location by one and we're simply returning the number, which is, well, in
our case, it's going to be zero.
And we want to keep going, keep going, keep going.
Well until Current is no longer bigger than last.
In that case, we're simply going to raise a stop iteration because there's no more things to iterate
over.
Let's see if this works.
I'm going to run this.
And look that it's all working.
I was able to loop through my generator and print I from zero all the way to 99.
Again, if we go back to our example here.
And I know this is a little hard to look at it at first.
But all I did was say I want an IT function to have the option of first and last.
And I'm going to want to be able to iterate through this object that I'm going to create.
And I also want to be able to use the next which for loop, if you remember from our previous example,
needs.
So I'm going to say four item in Jen.
Just loop through it.
I'm able to loop through it because this is now an iterator and I'm able to use the next value on it
because I allow us to loop and constantly increase by one.
Until we keep returning the number.
Keep returning the number until my gen current becomes 101 hundred is not less than 100, which is self
less.
So it's going to raise a stop iteration.
The for loop automatically catches us so it doesn't error out and it stops looping.
That's how things work underneath the hood with range.
Now, you don't need to know this.
You're not going to be asked in your day to day to implement this.
But I wanted to show you that this is how things work.
I think that's important.