Starting Note
Before reading this blog, I want to make a clear statement that this blog is written completely based on my understanding about how generators work in python. To move forward, you must be an intermediate in python.
Iterators
An object that contains countable number of values. The next value can be accessed with the next(object_name)
parameter
You can know more about iterators here: Iterators by W3 Schools
Case
Let's say you are working in a company and your company gives you a task to write a program to find a series of numbers. Each number having a difference of 12 from the previous. So the series is like: [12,24,36,48.....]
You have to find the series till a number given by the user and store the results somewhere so that others get those values using a loop.
So, if the user enters 10, the program will return a series like: 12,24,36,........,120
You will be like: Okay that's easy
def gen_series():
n = int(input("What's n? "))
a = []
d = 11
for i in range(1, n+1):
a.append(i + d)
d += 11
return a
if __name__ == "__main__":
print(gen_series())
Now, your program works nicely if the user inputs numbers like 12, 23, 89, 74.
If you test this code yourself and you enter a number like 1000000000000000 then what happens? Your code starts to hang, the program doesn't work smoothly. So, this is not the best approach to get a series of numbers.
Let's refactor this code a bit
def gen_series():
n = int(input("What's n? "))
a = series(n)
print(a)
def series(n):
a = []
d = 11
for i in range(1, n+1):
a.append(i + d)
d += 11
return a
if __name__ == "__main__":
gen_series()
Now, the program runs the same but our problem is not yet solved. We want to generate a series of numbers with each number having a difference of 12 from the previous and we want our program to generate as much numbers as we want.
Try to run this code:
def gen_series():
n = int(input("What's n? "))
a = series(n)
print(a)
def series(n):
d = 11
for i in range(1, n+1):
yield i + d
d += 11
if __name__ == "__main__":
gen_series()
If you run this code and input a number as 20, you will see the output as <generator object series at 0x0000020B20684350>
. Now, if you run again, and input a big number such as 1000000000000000, you will notice that your program doesn't lag. It works perfectly fine and you get the output.
The yield
keyword is responsible to make this function a generator.
The series
function is now a generator function which generates an iterator. If you have read the article of W3 Schools, you will certainly know that we can easily access the values from an iterator using a loop.
So, here's the definition of generators
Generators
Generators are those kind of functions that return an iterator.
Back to program
Now to print the values of the series we can use another function
def print_series():
a = gen_series()
for i in a:
print(i)
The complete code:
def gen_series():
n = int(input("What's n? "))
a = series(n)
print(a)
return a
def print_series():
a = gen_series()
for i in a:
print(i)
def series(n):
d = 11
for i in range(1, n+1):
yield i + d
d += 11
if __name__ == "__main__":
print_series()
Conclusion
- Generators are functions that return an iterator
- We can turn a normal function to generator by using the
yield
keyword
If you didn't understand then don't forget to criticize me in the comments. That will help me to come up with a better explanation. It is okay to criticize me if I have wasted your time. Also if you have any questions, please ask me in the comments