Generator functions in Python

Generator functions are like normal functions, coded with normal def statements, and when created they are compiled into an object that supports the iteration protocol. When called, they don’t return a result but they return a result generator that can appear in any iteration context.

A generator function yields a value, rather than returning one.

Generators are:

  • A type of iterable (like lists or tuples)
  • They don’t allow indexing with arbitrary indices
  • They can be iterated through with for loops
  • They can be created using functions and the yield statement

Example:

>>> def countdown():
...     i = 5
...     while i > 0:
...             yield i
...             i -= 1
... 
>>> for i in countdown():
...     print(i)
... 
5
4
3
2
1

Note:
The yield statement is used to define a generator, replacing the return of a function to provide a result to its caller without destroying local variables.

Due to the fact that they yield one item at a time, generators don’t have the memory restrictions of lists.
In fact, they can be infinite!

Example:

def many_sevens():
	while True:
		yield 7

for i in many_sevens():
	print(i)

The terminal output will be many 7s.

In short, generators allow you to declare a function that behaves like an iterator, i.e. it can be used in a for loop.

Finite generators can be converted into lists by passing them as arguments to the list function.

Example:

>>> def numbers(x):
...     for i in range(x):
...             if i % 2 == 0:
...                     yield i
... 
>>> print(list(numbers(11)))
[0, 2, 4, 6, 8, 10]

Benefits of using generators:

  • Improved performance
  • Lower memory usage
  • No need to wait until all the elements have been generated before start using them

Leave a Reply