Best Lesson on Python Generator and Generator Expressions


1. Python Generators

In Python, we’ve learned about Python functions. In that, we’ve seen in-built and user-defined functions. But in this tutorial, we will discuss Python generators, Python generator expression, and how to use generators in python. To find out, read more.

2. Python Generators Explained

A Python3 generator is a kind of an iterable, like a Python list or a python tuple. It generates for us a sequence of values that we can iterate on. You can use it to iterate on a for-loop in python, but you can’t index it. Let’s take a look at how to create one with python generator example.

python generators

Python Generators

a. Syntax of Generator in Python3

To create python3 generators, we use the yield statement, inside a function, instead of the return statement. Let’s take a quick example.

>>> def counter():
i=1
while(i<=10):
yield i
i+=1

With this, we defined a generator called counter(), and assigned 1 to local variable i. As long as i is less than or equal to 10, the loop will execute. Inside the loop, we yield the value of i, and then increment it.

Then, we iterate on this generator using the for-loop.

>>> for i in counter():
print(i)

1

2

3

4

5

6

7

8

9

10

b. Working of Python Generators

To understand how this code works, we’ll start with the for-loop. For each item in the generator (each item that it yields), it prints it, here.

We begin with i=1. So, the first item that it yields is 1. The for-loop prints this because of our print statement. Then, we increment i to 2. And the process follows until i is incremented to 11. Then, the while loop’s condition becomes False.

However, if you forget the statement to increment i, it results in an infinite generator. This is because a generator needs to hold only one value at a time. So, there are no memory restrictions.

>>> def even(x):
while x%2==0:
yield 'Even'
>>> for i in even(2):
print(i)

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

Even

EvenTraceback (most recent call last):
File "<pyshell#24>", line 2, in <module>
print(i)

KeyboardInterrupt

Here, since 2 is even, 2%2 is always 0. Hence, the condition for while is always true. Because of this, the Python3 generator even() keeps yielding the value True until we hit Ctrl+C on the keyboard to interrupt the execution.

Note that a generator may contain more than one Python yield statement. This is comparable to how a Python generator function may contain more than one return statement.

>>> def my_gen(x):
while(x>0):
if x%2==0:
yield 'Even'
else:
yield 'Odd'
x-=1
>>> for i in my_gen(7):
print(i)

Odd

Even

Odd

Even

Odd

Even

Odd

3. Yielding into a List

This one’s a no-brainer. If you apply the list() function to the call to the generator, it will return a list of the yielded values, in the order in which they are yielded. Here, we take an example that creates a list of squares of numbers, on the condition that the squares are even.

>>> def even_squares(x):
for i in range(x):
if i**2%2==0:
yield i**2

To create a list, we just apply the list() function to the call to this generator. We do not iterate on it using a for-loop.

>>> print(list(even_squares(10)))

[0, 4, 16, 36, 64]

As you can see, in numbers 1 to 9 (not 10, because range(10) gives us 0 to 9), the even squares are 0, 4, 16, 36, and 64. The others, that are 1, 9, 25, 49, 81 are odd. So, they’re not yielded.

4. List vs Generator in Python

This is a very simple difference. A list holds a number of values at once. But a generator holds only one value at a time, the value to yield. This is why it needs much less space compared to a list. With a generator, we also don’t need to wait until all the values are rendered.

5. Python Generators vs Functions

Now, to compare a generator to a function, we first talk about return and Python yield. When the interpreter reaches the return statement in a function, it stops executing the Python Generator  function, and executes the statement after the function call. However, when it reaches the Python yield statement in a generator, it yields the value to the iterable. Finally, it gets back to the generator to continue for the next value.

Also, when a function stops executing, its local variables are destroyed. This is not the same with a generator. Take a look.

>>> def mygen():
i=7
while i>0:
yield i
i-=1
>>> for i in mygen():
print(i) 

7

6

5

4

3

2

1

6. Python Generator Expressions

Just like a list comprehension, we can use expressions to create python generators shorthand. Let’s take a list for this.

>>> mylist=[1,3,6,10]
>>> (x**2 for x in mylist)
<generator object <genexpr> at 0x003CC330>

As is visible, this gave us a generator object. But to access the values, we need to store this into a variable, and then apply the next() function to it.

>>> a=(x**2 for x in my_list)
>>> next(a)

1

>>> next(a)

9

>>> next(a)

36

>>> next(a)

100

>>> next(a)
Traceback (most recent call last):
File "<pyshell#89>", line 1, in <module>
next(a)

StopIteration

7. Conclusion

Now that you know the benefits of python generators over a list or over a function, you will understand its importance. Some things, we can do with a generator, with a function, or even with a list comprehension. But using a generator is the most efficient. Tell us what you think.

Refer Best Python books to learn more.

Leave a comment

Your email address will not be published. Required fields are marked *