In [1]:
%autosave 10


Autosaving every 10 seconds

(wait for IPython Notebook to get posted)

  • !!AI look in 2013-talks, found a copy of the talk. go through it make notes.

 Background


In [2]:
def f(x):
    return x+1, x+2
f(10) == (11, 12)


Out[2]:
True

In [3]:
def f(x):
    yield x+1
    yield x+2
list(f(10)) == [11, 12]


Out[3]:
True

Generators require iteration over results.

Callable


In [4]:
class Callable(object):
    def __call__(self, x):
        return x+1, x+2
Callable()(10) == (11, 12)


Out[4]:
True

Iterable

  • __iter__, __next__

Generators

At the C-level, generators are functions that leave state behind when yielding. It just jumps over the cleanup.

Coroutines

  • Functions have one entry, one exit, and eagerly return results.
  • Coroutines have multiple entries, multiple exits, and lazily return results.
  • throw, send, close.
    • throw: throw exception during iteration.
    • close: halt a generator, clean up state.
    • send: send value back into a generator.

In [8]:
def generator(x):
    y = None
    y = yield x+1, y
    y = yield x+1, y

g = generator(10)
print g.next()
print g.send("abc")


(11, None)
(11, 'abc')

Pumping and priming

  • One annoyance.
  • Can't inject value before first yield into a generator/coroutine.
  • "Can't send non-None to a just-started generator"
  • You'll see "pump" or "prime" decorator in large projects.

Itertools

  • 2nd out of 23 favourite Python modules.
  • Generators is one of the core features of Python.
  • izip, islice help you manipulate iterables without caring about their contents.
    • e.g. can't concatenate a list and a tuple natively.
    • but chain just connects iterables, doesn't care.
  • Want to dscompose problem into composition of streams, and don't need to bring everything into memory.

In [ ]: