

In this lesson you learn about, generator functions in Python.

What is a generator ?

A generator is special type of iterator,

you can only iterate though them only once.

Generator functions are memory efficient.

Normal functions use ‘return’ keyword to return a value.

Where as generator functions use ‘yield’ keyword to return value.

Generators generate elements on the go, instead of creating all elements at once.

Before we move further, Let’s look at an example.

You might have already used range() built-in function.

Which is a generator function.



range() is a generator

range([start],end,[step]) type(range(10)) output: range

We can check how range() is memory efficient, by creating different

size range object and checking the size of object.

To check size of the object in memory, we will make use of

getsizeof() function of sys module.



Ex 1:



Create a range object of size 10.



from sys import getsizeof r1 = range(10) getsizeof(r1) ouput: 48



Ex 2:



Create a range object of size 100.



r2 = range(100) getsizeof(r2) output: 48



Ex 3:



Create a range object of bigger size, lots of zeros.



r3 = range(100000000000000) getsizeof(r3) output: 48



Irrespective of number of objects range() generators,

The size of the object remains the same, because its

generating one item at a time.



Creating a generator function



You can create your generator function, using yield keyword,

instead of return.



syntax:



def function_name([args]): yield

So what is generator function ?



A function with yield keyword, is a generator function.



Let’s create some generators.



Ex 1:



difference between a normal and generator function



simple function to return a value



def simple_function(): return 10 f1 = simple_function() f1 output: 10



simple_function returns a value, 10



simple generator function to return generator object.



def simple_generator(): yield 10 g1 = simple_generator() g1 output: <generator object simple_generator at 0x000001C6FDE5DBF8>



simple_generator() returns a generator object.



But how to access the value of generator?



You can use next() to access values.

or by iterating through generator object using for-loop.



next(g1) output: 10

You can use next() function to get the values, until the generator exhausts.

Once generator reaches end, it throws StopIteration exception.

In above example, simple_generator() yields only one value,

and we have accessed it by next(g1).

If next(g1) is called again, you will get StopIteration.

next(g1) output: --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-5-9abcc56105c0> in <module>() ----> 1 next(g1) StopIteration:

Don’t use return and yield together in a function.

Ex 2:



Generator function to generate cube of numbers.



def gen_cubes(n): for num in range(n): yield num**3 gen_cubes(10) output: <generator object gen_cubes at 0x000001C6FDE5D620>



Generator object is created, now lets access the items

using for-loop.



for cube in gen_cubes(10): print(cube, end=" ") output: 0 1 8 27 64 125 216 343 512 729

Ex 3:

Generating Fibonacci numbers.

A Fibonacci series is a sequence of number, where a

number is sum of its two preceding numbers

1,1,2,3,5,8,13…… is a simple Fibonacci series.

def gen_fib(n): a = 1 b = 1 for i in range(n): yield a a,b = b,a+b for fib in gen_fib(10): print(fib, end=' ') output: 1 1 2 3 5 8 13 21 34 55

yield multiple values from a function



You can have multiple yield statements in a function, like return.

In the below function func(), yields ’10, 20, 30 and some string’

when it is called.

def func(): print('In func, yielding 10') yield 10 print('In func, yielding 20') yield 20 print('In func, yielding 30') yield 30 print("In func, yielding 'some string' ") yield 'some string' for yld in func(): print('for loop : yld = ',yld) output: In func, yielding 10 for loop : yld = 10 In func, yielding 20 for loop : yld = 20 In func, yielding 30 for loop : yld = 30 In func, yielding 'some string' for loop : yld = some string