## Thursday, January 28, 2010

### Sending data into a generator function

Generators and iterators are relatively new to Python. Here is a nice discussion of functional programming that has a lot of good information about them, as well as other topics.

There is some technical distinction between the terms. An interator is something you can invoke `next` on, and a generator function or expression is something that returns an iterator. At least that much, I think I understand. So this first example is a simple generator function for the Fibonacci series:

 `>>> def fib():... a, b = 1,1... while True:... yield a... a, b = b, a+b... >>> it = fib()>>> import itertools>>> list(itertools.islice(it, 10))[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]`

We use `islice` from `itertools` to get a slice from it. This setup has the disadvantage that we are computing two values ahead of the one we actually return, but it allows me to do the yield in only one place.

One great thing about iterators is that they allow you to deal with sequences that go on forever (like the Fibonacci sequence does) in a compact way. One can make a finite iterator like this:

 `>>> def f():... for i in range(3):... yield 2**i... raise StopIteration... >>> it = f()>>> for n in it: print n... 124>>> it = f()>>> list(it)[1, 2, 4]`

The next example uses an "advanced" feature of iterators. It is possible to code it so that a value can be passed into the generator function by use of the `send` method. See here. In this contrived example, we simply advance the generator a given number of steps:

 `>>> def fib():... a, b = 1,1... while True:... value = (yield a)... try:... if value:... value = int(value)... except ValueError:... value = None... if value:... for i in range(value):... a, b = b, a+b... else:... a, b = b, a+b... >>> it = fib()>>> it.next()1>>> it.send(5)8>>> import itertools>>> list(itertools.islice(it, 10))[13, 21, 34, 55, 89, 144, 233, 377, 610, 987]`

The call to `send` does a yield thing.

A more serious use of send is described by Alex Martelli here (in the first answer to the question).