An Introduction to Python Generators

Tuesday, July 7, 2009

I have always heard about the term generators in python, went through many tutorials, but time and again it puzzles me when going through the code after a long time, generators is one of the important features of python whereby one can generate a series of values while maintaining the state of the function, consider generators as a function which when invoked will return a value and halts execution at that point till you invoke the next() function to continue its execution.

How can such a function be possible, isn't a function returning a value gets terminated at that moment, the answer is "yes" for normal functions, but a generator function returns a value not through return statement, but through an yield statement, in other words, the function yields a value at that point of time (when an yield statement is encountered) until its invoked again whereby it completes another cycle till an yield statement is encountered where it returns another value and so on, it has to be noted that such a function can also be terminated, lets look at a factorial example which I hope would be a simple and yet a handy reference.

Listing 1: generators_factorial_1.py

1.  # generators_factorial_1.py
2. # A simple factorial program using python generators
3. # Author: S.Prasanna
4.
5. def factorial():
6. """ Factorial sequence using generators. """
7. count = 1
8. fact = 1
9. while 1:
10. yield fact
11. count = count + 1
12. fact = fact * count
13.
14. if __name__ == "__main__":
15. print "Factorial program using generators."
16. func = factorial()
17. print "Factorial of 1 =", func.next()
18. print "Factorial of 2 =", func.next()
19. print "Factorial of 3 =", func.next()
20. print "Factorial of 4 =", func.next()
21. print "Factorial of 5 =", func.next()
Output:

Factorial program using generators.
Factorial of 1 = 1
Factorial of 2 = 2
Factorial of 3 = 6
Factorial of 4 = 24
Factorial of 5 = 120

Explanation:

As I mentioned earlier, a generator function works like a normal function until it hits an yield statement (line 10) where it returns a value (yield fact returns the value of fact at that moment) and halts there, maintaining the state of all the variables and the point where it yielded a value, then using the next() method, one can continue the execution of the function where it continues from where it left for another cycle till its an yield is encountered and so on, in this way we can generate a sequence of values like Fibonacci, factorial, square of numbers and so on.

The above code can be improved by using an iterator which calls the next() function automatically as shown below.

1.  # generators_factorial_2.py
2. # A simple factorial program using python generators with iterations
3. # Author: S.Prasanna
4.
5. def factorial(n):
6. count = 1
7. fact = 1
8. while count <= n:
9. yield fact
10. count = count + 1
11. fact = fact * count
12.
13. if __name__ == "__main__":
14. print "Factorial program using generators."
15. for i in factorial(5):
16. print i
Output:

Factorial program using generators.
1
2
6
24
120

Explanation:

The above code is similar to listing 1 except that the for loop (lines 15 - 16) takes care of calling the next() function for you for five times and everytime the generator function yields a value, the for loop body executes, when the generator function terminates, the for loop terminates as well.

But wait, as a core python programmer, I won't be stopping here as far as the use of generators are concerned, look out for another sophisticated use of generators in this blog.

No comments:


Copyright © 2008 Prasanna Seshadri, www.prasannatech.net, All Rights Reserved.
No part of the content or this site may be reproduced without prior written permission of the author.