#!/usr/bin/env python # coding: utf-8 dojo-20130607 nested generators tuple unpacking # Here's the old style generator that did everything in one generator. # In[1]: def gen_even_fibonacci(last): a = 0 b = 1 while True: c = a + b a = b b = c if b > last: break if b % 2 == 0: yield b # In[2]: [i for i in gen_even_fibonacci(1000)] # Now let's be more modular with more generators, where each generator does one thing well, and they can be combined with other generators. Each one is simple and easy to understand. This is like the Unix philosophy. # In[3]: def gen_fibonacci(): a, b = 0, 1 while True: a, b = b, a + b yield b # In[4]: def gen_even(gen): for i in gen: if i % 2 == 0: yield i # In[5]: def gen_lte(gen, n): for i in gen: if i > n: break yield i # Now we get to the benefit. We can combine generators much like one combines Linux shell commands with pipes on the command line. # In[6]: [i for i in gen_lte(gen_even(gen_fibonacci()), 1000)] # In[7]: [i for i in gen_lte(gen_fibonacci(), 1000)] # In[8]: evens = (i for i in gen_fibonacci() if i%2 == 0) [i for i in gen_lte(evens, 1000)] # In[9]: evens = gen_even(gen_fibonacci()) [i for i in gen_lte(evens, 1000)] # In[10]: [i for i in gen_lte(gen_even(gen_fibonacci()), 1000)] # It's easy to create new generators that can be combined with others. # In[11]: def gen_n(gen, n): for i in gen: if n <= 0: break yield i n -= 1 # In[12]: [i for i in gen_n(gen_fibonacci(), 10)] # In[13]: [i for i in gen_n(gen_even(gen_fibonacci()), 10)] dabeaz: Daved M. Beazley Generator Tricks for Systems Programmers - Version 2.0 http://www.dabeaz.com/generators-uk/index.html nested generators use like pipes # In[14]: fibs = gen_fibonacci() evens = gen_even(fibs) lte = gen_lte(evens, 100) [i for i in lte]