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.
- A type of iterable (like lists or tuples)
- They don’t allow indexing with arbitrary indices
- They can be iterated through with
- They can be created using functions and the
>>> def countdown(): ... i = 5 ... while i > 0: ... yield i ... i -= 1 ... >>> for i in countdown(): ... print(i) ... 5 4 3 2 1
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!
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
Finite generators can be converted into lists by passing them as arguments to the list function.
>>> 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