[Python-checkins] r46250 - sandbox/trunk/Doc/functional.rst

Raymond Hettinger rhettinger at ewtllc.com
Thu May 25 22:59:11 CEST 2006


Inserted below are a few ideas that you may or may not want to include 
as part of a tutorial of functionals.

>+``itertools.count(n)`` returns an infinite stream of
>+integers, increasing by 1 each time.  You can optionally supply the
>+starting number, which defaults to 0::
>+
>+        itertools.count() =>
>+          0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...
>+        itertools.count(10) =>
>+          10, 11, 12, 13, 14, 15, 16, 17, 18, 19, ...
>  
>

count() is typically used to feed consecutive numbers into other 
itertools.  For example: imap(f, count())  -->  f(0), f(1), f(2), . . .

Since count() is an infinite iterator, one of the enclosing functions is 
typically responsible for termination.  For example, izip() will 
terminate whenever one of its input streams is exhausted, so you can 
write a variant of enumerate with:  izip(count(1), 'abc') --> (1,'a'), 
(2,'b'), (3,'c') StopIteration.  This same thought applies to other 
infinite iterators like repeat(value) or cycle(seq).


>+
>+``itertools.repeat(elem, [n])`` returns the provided element ``n``
>+times, or returns the element endlessly if ``n`` is not provided.
>+
>+::
>+
>+    itertools.repeat('abc') =>
>+      abc, abc, abc, abc, abc, abc, abc, abc, abc, abc, ...
>+    itertools.repeat('abc', 5) =>
>+      abc, abc, abc, abc, abc
>  
>
One common use is supplying a stream of constants to multi-valued 
functions.  For example, to create consecutive powers of three:  
imap(pow, repeat(3), xrange(10)) --> 3**0, 3**1, 3**2, ..., 3**9

It can also be useful in speed critical fixed-length loops that do not 
need an index:

   for _ in repeat(None, 10): print "hello"        # Ten hellos


>+
>+``itertools.chain(iterA, iterB, ...)`` takes an arbitrary number of 
>+iterables as input, and returns all the elements of the first iterator, 
>+then all the elements of the second, until all of the iterables 
>+have been exhausted.
>+
>+::
>+
>+    itertools.chain(['a', 'b', 'c'], (1, 2, 3)) =>
>+      a, b, c, 1, 2, 3
>  
>
One obvious use is removing one level of for-loops when iterating over 
multiple sequences:

    for s in s1, s2, s3:
         for x in s:
             print f(x)

simplifies to:

    for x in chain(s1, s2, s3):
        print f(x)

Another use for chain() is to pad sequences with a fill value:

   s = 'ABC'
   t = 'uvwxyz'
   zip(chain(s, repeat('-', 3), t)

Another variant on that theme is padding a short sequence with fill 
values so that zip() can form the sequence into a two dimensional array:

    >>> s = range(11)
    >>> zip(*[iter(chain(s, repeat(0,5)))]*5)
    [(0, 1, 2, 3, 4), (5, 6, 7, 8, 9), (10, 0, 0, 0, 0)]



>+
>+``itertools.izip(iterA, iterB, ...)`` takes one element from each iterable
>+and returns them in a tuple::
>+
>+    itertools.izip(['a', 'b', 'c'], (1, 2, 3)) =>
>+      ('a', 1), ('b', 2), ('c', 3)
>+
>+This iterator is intended to be used with iterables that are all of
>+the same length.    If the iterables are of different lengths, 
>+the resulting stream will be the same length as the shortest iterable.
>+Unfortunately, if you passed in any iterators as arguments, 
>+an element may have been taken from the longer iterators 
>+and discarded, meaning that you can't keep using them; if you do, 
>+you risk skipping a discarded element.
>+
>+::
>+
>+    itertools.izip(['a', 'b'], (1, 2, 3)) =>
>+      ('a', 1), ('b', 2)
>  
>
The izip() tool is typically used in for-loops to have lock-step 
iteration over multiple sequences:

    for x, y in izip(xseries, yseries):
            print 'Coordinate', x, y

Used with a for-loop, the izip() tool typically outperforms its built-in 
zip() counterpart.

The izip() tool can be used with the * operator to have the effect of a 
matrix transpose:

   >>> m = [(1,2,3), (4,5,6)]
   >>> list(izip(*m))
   [(1, 4), (2, 5), (3, 6)]

There is another * operator trick to make zip() or izip() serve as a 
data grouper:

   >>> zip(*[iter(s)]*3)
   [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, 11)]



If you want more of these kinds of comments or examples, let me know and 
I'll cover the rest of the tools.


Raymond


More information about the Python-checkins mailing list