Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Gentle Introduction to Generators and Coroutines

Kiran
November 26, 2014

A Gentle Introduction to Generators and Coroutines

Kiran

November 26, 2014
Tweet

More Decks by Kiran

Other Decks in Programming

Transcript

  1. A Gentle Introduction to
    Generators
    Coroutines
    and

    View full-size slide

  2. Hello!
    Hacker/Programmer @ WalletKit, Inc.
    Open Source Enthusiast
    Python Fanboy
    @kirang89
    http://kirang.in

    View full-size slide

  3. Generators
    Coroutines

    View full-size slide

  4. Let’s back up a bit

    View full-size slide

  5. Functions
    Takes some input
    Returns some output (or flow of control)
    Stateless

    View full-size slide

  6. Now consider a new type of function
    Pretty much the same (Well, almost)
    Remembers state after returning flow of control
    Instead of returning, it yields some output

    View full-size slide

  7. yield = return + sorcery*
    * It’s not all that magical from a computer’s perspective

    View full-size slide

  8. Generator Functions
    a.k.a
    Generators
    Functions that ‘yield’ are called

    View full-size slide

  9. Coz they’re
    Why are Generators awesome?
    Lazy

    View full-size slide

  10. def infinite_seq():
    i = 0
    while True:
    yield i
    i = i +1
    https://projecteuler.net/problem=10
    OR

    View full-size slide

  11. def fibonacci_gen():
    a, b = 0, 1
    while True:
    yield b
    a, b = b, a + b

    View full-size slide

  12. >>> f = fibonacci_gen()
    >>> type(f)

    >>> f

    View full-size slide

  13. Print first 5 terms of the fibonacci series
    f = fibonacci_gen()
    print(next(f)) # Prints 1
    print(next(f)) # Prints 1
    print(next(f)) # Prints 2
    print(next(f)) # Prints 3
    print(next(f)) # Prints 5

    View full-size slide

  14. Using Generators
    - Generator Functions
    - Generator Expressions

    View full-size slide

  15. def even_range(n):
    for i in range(n):
    if i % 2 == 0:
    yield i
    vs
    even_range_10 = (a for a in range(10) if a % 2 ==0)

    View full-size slide

  16. Performance ?
    Memory Usage ?

    View full-size slide

  17. kiran:~/ $ python -m timeit "s=[a for a in range(1000000)]”
    10 loops, best of 3: 61.3 msec per loop
    70 MB
    kiran:~/ $ python -m timeit "s=(a for a in range(1000000))"
    10 loops, best of 3: 16.4 msec per loop
    ~66 MB
    kiran:~/ $ python -m timeit "s=(a for a in xrange(1000000))"
    1000000 loops, best of 3: 0.802 usec per loop
    ~3.4 MB

    View full-size slide

  18. Generators
    Coroutines

    View full-size slide

  19. Co-operative Multitasking/Communication
    via
    Enhanced Generators

    View full-size slide

  20. Enhanced ?
    Allow values/exceptions to be passed as arguments
    when a generator resumes

    View full-size slide

  21. yield as a keyword
    yield as an expression
    vs

    View full-size slide

  22. Receive a value value = (yield)
    Send a value coroutine.send(data)
    Close coroutine.close()

    View full-size slide

  23. def match(pattern):
    print('Looking for ' + pattern)
    try:
    while True:
    s = (yield)
    if pattern in s:
    print(s)
    except GeneratorExit:
    print("Done")

    View full-size slide

  24. >>> matcher = match('python')
    >>> matcher.send(None)
    Looking for python
    >>> matcher.send('Hello World')
    >>> matcher.send('python is awesome!')
    python is awesome!
    >>> matcher.close()
    Done

    View full-size slide

  25. Let’s look at a bit more
    awesome
    example

    View full-size slide

  26. def word_count():
    wc = 0
    try:
    while True:
    _ = (yield)
    wc = wc + 1
    except GeneratorExit:
    print "Word Count: ", wc
    pass
    def match(pattern, counter):
    print('Looking for ' + pattern)
    try:
    while True:
    s = (yield)
    if pattern in s:
    counter.send(None)
    except GeneratorExit:
    counter.close()
    print("Done")
    def parse(file, matcher):
    f = open('sampleset.txt', 'r')
    for line in f.readlines():
    for word in line.split(' '):
    matcher.send(word)
    matcher.close()

    View full-size slide

  27. counter = word_count()
    counter.send(None)
    matcher = match('python', counter)
    matcher.send(None)
    parse('sampleset.txt', matcher)

    View full-size slide

  28. We’ve not even scratched the surface!

    View full-size slide

  29. Resources
    - PEP 255 (Generators)
    - PEP 289 (Generator Expressions)
    - PEP 342 (Coroutines)
    - http://www.dabeaz.com/coroutines/

    View full-size slide