Hello guys.
So we are going to continue our discussion with respect to Python.
And in this video we are going to talk about generators.
Already we have discussed about iterator.
Uh one very important thing about generator is that it is a subclass of iterator itself okay.
And it is a like generator are a simple way to create iterators.
They use the yield keyword to produce a series of values lazily, which means they can generate value
on the fly and do not store them in the memory.
And that is how efficient memory management and looping basically happens.
Okay, now in order to show you one good example, that how with the help of generator, we are able
to create a iterator.
We will be discussing over here.
And I will just take a very simple example.
Let me just go ahead and create a function.
Let's say um square okay.
So square is the function over here I'll give my n keyword okay.
Uh or let's say this n value will be there.
And what I will do, let's say if I'm giving n is equal to three.
Right.
So I will go ahead and write for I in range of three.
Okay, I in range of three.
And now what I will be doing is that I will just go ahead and say, hey, let's return I to the times
two.
So we are basically squaring that particular number.
But what is basically happening over here right now, we are iterating through a collection and we are
returning one only one square, right.
So if I go ahead and execute this okay.
Now just see this okay.
If I just go ahead and execute this and if I just call square of three.
So what output I'm actually going to get zero.
Why.
Because it iterates through all the elements over here.
But the first element is zero.
But it is returning zero multiplied like zero to the times of two.
Right.
And obviously I'm just going to get the answer as zero.
But what I want is that I want to iterate through all the elements as we iterate in the iterator itself.
So in generator, when we are creating this kind of iterators, we use a yield keyword.
Okay.
Now with the help of this yield keyword, what will happen?
This yield keyword will create a local variable and it will save the values also.
Now if I go ahead and execute square of three right now see this?
Okay.
If I just go ahead and execute this just by using this yield keyword.
And I'm just going and executing the square of three, it shows it is a generator object square at this
specific memory location.
Now this has actually got converted into a generator object.
And generators are nothing.
But it is a simple way to create iterators.
And here we are also using functions.
Okay.
Now in order to iterate through this particular elements, what I can actually do, I can go ahead and
write for I in for I in square of three.
Let's say if I go ahead and write for I in square of three, and here if I go ahead and print, I now
see the magic.
Okay.
Now what will happen if I run this iteration?
Okay.
So for let's say that here I will go ahead and write for I in square of three.
Now square of three, it will go over here then over here.
For I in range of three it will become.
Then it will yield.
Yield basically means zero zero to the power of two.
Now this yield.
It will do.
It will save this first operation.
And it will return the value over here and it will print it.
Okay.
Then again it will go inside this square.
It will go to the next, next value.
That is one.
Again it will go ahead and do this particular operation.
And whenever we say yield it is going to save that particular value.
And it is also going to return it.
Okay.
And as soon as it is getting returned over here we are also going to print it.
Okay.
So now if I go ahead and execute this see the magic over here I'm getting zero one and four.
Right.
So I hope you are able to understand the very importance of this yield keyword.
This yield keyword is specifically it produces a series of values lazily, which means they can generate
values on the fly and do not store them in the memory.
They are just storing it over here, and they are just displaying it, and they are just passing it
from the main function where it is called, or from the main code where it is called.
Right.
So this clearly shows that how you are able to access it.
Okay.
Let's say that I will just go ahead and write like this.
So this is one way of probably calling this all the iterator elements.
The other way is that if I go ahead and create the square of three and let's say I go ahead and display
store this particular variable in a, if I go ahead and execute, this becomes a generator object over
here right now.
In order to iterate through this, I can again write next of a right.
If I go ahead and write next of a, the first element is zero.
See?
Then again, if I go ahead and hit next of a, the second element is one, and then again if I hit,
it is nothing but four.
And that is what I got over here.
014 and finally, if I again hit there are no elements.
So I'm going to get this stopiteration error.
So in short, what has happened is that we have used generator and we have also converted or we have
created iterators with the help of this particular function.
And here I've also shown you an importance of this particular yield keyword yield keywords, whatever
operation I'm actually doing it over here.
It is also returning the value where I'm actually calling it from okay.
This is the main importance of the yield keyword.
Okay.
Let me just go ahead and show you one more example.
Let's say that I'm going to go ahead and create my another function.
Let's say I'll go ahead and write my generator okay.
And here we are going to write yield of one okay.
So let's say that I'm for the first time I'm returning yield of one.
Then I will go ahead and write yield of two.
Then I will have yield of three.
Now this is the most amazing thing about generators is that we can we can return multiple values also
like return multiple yield values also.
Okay.
Now let me just go ahead and execute it okay.
And if I go ahead and create an or if I just call this particular my generator over here okay.
So if I go ahead and just print this what is this generator.
It is nothing.
But it is a generator object at this specific memory location.
Now in order to iterate through this, what I can do, I can go ahead and write next object.
So next object.
First of all what is the first yield.
Here you can see yield one right.
Then the next yield is two.
Then the next yield is three.
Then again if I go ahead and execute again it is stop iteration.
Now let me just go ahead and execute again this one.
And now what I will do I will just go ahead and show you with the help of for loop.
Also, I'll go ahead and write for Val in.
Jen.
Okay, Jen.
And now if I go ahead and print the value now because of this yield, first time it is going to display
one then two, then three.
See 123.
Right.
So here you can see that this yield one.
This one will be getting saved over here.
It will just return it from where I'm actually calling using the next Jen.
And during the fly all the values are getting generated.
But my entire object is basically created in this particular memory location.
And one by one we can iterate through all the elements through this particular yield keyword.
Right.
So I hope you are able to understand this amazing thing.
Okay.
Now let me just show you one practical example of using generator okay.
So generator uh, one very good example that I would like to give one practical example that is reading
large files.
Okay.
So let me just go ahead and provide some definition over here.
Okay.
Let me just go ahead and make some markdown so that you will also be able to understand it.
Okay.
So let me just quickly write it down over here.
So here you can see some of the practical example.
And we'll try to implement this generator are particularly useful for reading large files because they
allow you to process one line at a time without loading the entire file into the memory.
If you have a large file, you can specifically use generator and load chunks from that particular file
itself.
Display it without loading into the entire memory.
Right?
And this is the most amazing thing.
So let me do and go ahead and create one function.
So here I will write definition read underscore large underscore file okay.
And here I'm actually going to give my file path.
So let's say that this is my file path.
Now I will go ahead and use with open.
And let's say I'm going to use file underscore path in the read mode.
Okay.
Whatever file path is there in the read mode.
After opening this, I'll create a file object.
Okay.
And then let me just go ahead and say for line, for every line in file we are just going to yield.
I'm writing yield line.
So what it is going to do it will just take a line.
It will display it over here or it will just return it from where I'm actually calling.
Okay.
So let me just go ahead and create one of the file over here.
So let's say this is my large uh, large underscore file dot text okay.
And what I will do is that I will just go ahead and probably take a big article and paste it over here.
Uh, I will just search for president of India.
So I'm doing a Google search in my separate browser okay.
And I will just paste it over here, some text.
I will try to paste it so that it becomes a large file.
Okay.
So just give me a second okay.
So I'm just going to paste some information over here.
Okay.
So this is the information about the president of India that is Srimati Draupadi Murmu.
So I'm just going to save this okay.
And now I'm going to read this particular file.
So let me just go ahead and execute this.
So this basically becomes my iterator over here.
This entire function is now my iterator.
Okay.
Now let me just call this.
So I'm going to go ahead and write file underscore path is equal to large file large underscore file
dot txt which I've actually created it over there.
And then I'll go say for line in read large file.
And here I'm going to give my file path okay.
I'm going to give my file path.
And here I'll just go ahead and say print line dot strip.
Now you know that over here I've used the yield.
Right.
So as soon as it will read one line it is going to probably display it over here.
Now here you can see how quickly we are able to execute it and understand this entire thing has been
done with the help of a generator, and the best thing is that I have not even saved the entire file
into the memory.
And this is what is basically getting displayed, right?
So I hope you are able to understand all these amazing things right.
And this is something a really advanced concept in generators that we specifically use.
Now just to talk about the differences between iterator and generator.
First of all, iterator you have to use iter keyword generator.
You have to use along with the function.
You have to use yield keyword.
Right.
Uh, generator uh, in short uses the yield keyword.
It saves the local variable.
So it saves the variable one by one.
And it just return to wherever we are.
Specifically calling generator in Python helps us to write uh, top uh fast and compact code.
Python iterator is much more efficient when compared to the generators.
Okay, so I hope you are able to understand about generators.
Guys, uh, this was the basic difference between iterators and generators and yes, this was it from
my side.
I will see you all in the next video.
Thank you.
Take care.