Python generators

Generator are simple implementation of iterator. When creating iterator object you have to implement __iter__() method, and then __next__() and then call it via iter() and next() method or in a loop.

Generator simplifies this process by providing yield keyword in a function. Once the function implements yield it can give data one at a time using next() method. You don’t have to implement __iter__() and __next__() methods , this will be implemented for you by the yield keyword. 

Difference between yield and return

yield returns data one at a time and when calling same function it will know the previous return state and return from next item. The return statement return the intended item and stops calling of the function. The yield halts the calling of function and returns items from next element.

Let’s a simple implementation of yield keyword in python

Example:

def my_generator():

    n = 0
    print('Value of n = ', n)
    yield n

    n += 1
    print('Value of n = ', n)
    yield n

    n += 1
    print('Value of n = ', n)
    yield n

data = my_generator()
# using next() method
next(data)
next(data)
next(data)

print("using for loop")
# using for loop
for i in my_generator():
    print(i)

Output:

Value of n =  0
Value of n =  1
Value of n =  2
using for loop
Value of n =  0
0
Value of n =  1
1
Value of n =  2
2

Generator inside loop

The yield statement can also be used inside a loop to perform various operations.

def square_of_number(limit=0):
    n = 1
    while n <= limit:
        yield n ** 2
        n += 1


for item in square_of_number(4):
    print(item) 

Output:

1
4
9
16

Generator expression

Generator can be created using generator expression in python. Generator expression use small bracket ( ( ) )  to form generator object.  Let’s see an example 

odd_num = [1, 3, 5, 7]
list1 = [x**2 for x in odd_num] # a list
gen1 = (x ** 2 for x in odd_num) # a generator

print(list1)
print(gen1)

Output:

[1, 9, 25, 49]
<generator object <genexpr> at 0x7f2470633518>

As you can see, list prints entire list elements where as printing gen1 results in a generator object. This generator object can be looped through similar to previous using next() method or using for loop. Let’s see an example.

Using next() method:

odd_num = [1, 3, 5, 7]
gen1 = (x ** 2 for x in odd_num)

print('Using next():')
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))

using for loop:

odd_num = [1, 3, 5, 7]
gen1 = (x ** 2 for x in odd_num)
print('Using loop:')
for i in gen1:
    print(i)

In generator one the object is iterated the item is not available. If you loop through the same generator element next time it will not result in any result. Let’s see going though generator object twice. First one will produce result but second one will not.

odd_num = [1, 3, 5, 7]
gen1 = (x ** 2 for x in odd_num)

print('Using next():')
print(next(gen1))
print(next(gen1))
print(next(gen1))
print(next(gen1))

print('Using loop:')
for i in gen1:
    print(i) 

Output:

Using next():
1
9
25
49
Using loop:

As you can see for loop did not output any result.

Leave a Reply

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