Iterators and Generators- It Ain't Your Gramp's Loop Any More.notes

Saturday, March 26, 2005

TITLE OF PAPER: Iterators and Generators: It Ain't Your Gramp's Loop Any More
URL OF PRESENTATION: _URL_of_powerpoint_presentation_
PRESENTED BY: Alex Martelli
REPRESENTING: _name_of_the_company_they_represent_

DATE: March 24, 2005
LOCATION: Marvin Theater

{If you've contributed, add your name, e-mail & URL at the bottom}

Started in the middle...

iter's Sentinel form

#  Handy for
def sentiter(f, sentinel):
    """Loop till the value yielded from an iterator is a certain arbitrary
        "sentinel" value."""
    while True:
        r = f()
        if r == sentinel: break
        yield r

A think out of the box usage
import random
randiter = iter(random.random, -1,0)
note: an infinite iterator

Infinite iterators--not really a problem; all you waste is the RAM to store the
    state of the iterator. "This is why we have the 'break' statement in 'for'
        <generation of fibonacci numbers>

"Peekable iterator"
    An iterator which wraps another iter and which lets you "peek" ahead -- maintains a lookahead cache (have a membersequence to represent the lookahead cache)
    a function containing keyword yield
    when called returns an iterator x starts executing body
    until it meets a yield y
        then it returns y and freezes the state
    or meets a return (or falls off the end)
        Then, it raises StopIteration.

Generator Expressions
    Like listcomps but for generators - use () instead of []

Make any loop a for loop
    Big code example: if you have a hairy "for loop" condition, break it off as
        a generator, and use all the time.
    Another example is to flatten tree-walking into a sequence iteration.
    Use generators to centralize code in a single place--DontRepeatYourself.
Encapsulate recursion (inside a generator)

Iterators: not just for's.
    co-routine like behavior

Infinite generators - use these to produce infinite iterators
    sieve of eratosthenes as a generator
    a module in the standard library
    build iterators, mostly from other iterators, sequences, or other iterables
        izip, ifler, islice, imap, stsarmap, tee, chain, takewhile, dropwhile,
    build potentially infinite iterators:
        count, cycle, repeat
    /fast/, fundamental, composable "building blocks" for many kinds of loops:
        skip items, truncate, whatever

itertools are *fast*
    for example, say we need to do something 1000 times:
        range() works, xrange() is better (sparse), but an iterator is even
                range(1000) 144us
                xrang(1000) 123 us
                itertools.repeat(0, 1000) 104us
        In fact, xrange() should be deprecated, he says.

Truncating infinities
    use itertools.islice itertools.takewhile
    list(it.takewhile(lambda x:x<X, primes()))  # a list of primes less than X

"Striding" w/ itertools
    traverse a sequence by a stride

REFERENCES: {as documents / sites are referenced add them below}


CONTRIBUTORS: {add your name, e-mail address and URL below}
Erik Rose <>
Ted Leun <> <>

E-MAIL BOUNCEBACK: {add your e-mail address separated by commas }

A headline (like a field in a database) will be CAPITALISED
    This differentiates from the text that follows
A variable that you can change will be surrounded by _underscores_
    Spaces in variables are also replaced with under_scores
    This allows people to select the whole variable with a simple double-click
A tool-tip is lower case and surrounded by {curly brackets / parentheses}
    These supply helpful contextual information.

Copyright shared between all the participants unless otherwise stated...