[Python-Dev] itertools module

Raymond Hettinger python@rcn.com
Mon, 27 Jan 2003 12:03:37 -0500


> I fixed a couple typos, but have a few (more subjective) comments:

Thanks for the rapid review.

> 
>     * islice() - The description seems a bit confusing to me - perhaps a
>       simple example would be useful.

I'll clarify the docs and add simple examples for each function.

islice is one of the more powerful functions:

        for line in islice(afile, 10, 20, 2):
                print line        # Starting with line 10, prints every other line
                                      # upto but not including line 20.

         nth = lambda iterable, n: islice(iterable,n,n+1).next()  # get the nth item

>     * takewhile()/dropwhile() - I assume these only return a prefix of their
>       iterable arguments.  Dropwhile()'s help suggests that, but
>       takewhile()'s description is more vague about the notion.

I'll clarify the docs and add clear examples.


>     * imap() - It's not clear to me why it differs from map() other than the
>       fact that it's an iterator.

The other differences are that it stops with the shortest iterable
and doesn't accept None for a func argument.

>  Can you motivate why it stops when the
>       shortest iterable is exhausted and doesn't accept Non for its func
>       arg?

Because one or more useful inputs are potentially infinite, filling in
Nones is less useful than stopping with the shortest iterator.

The function doesn't accept None for a function argument for
1) simplicity
2) we have zip() for that purpose

OTOH, if it is important to someone, I can easily re-embed that
functionality. 

>     * loopzip() - It's not clear why its next() method should return a list
>       instead of a tuple (again, a seemingly needless distiction with its
>       builtin counterpart, zip()).

I've wrestled with the one.
The short answer is that zip() already does a pretty good job
and that the only use for loopzip() is super high speed looping.
To that end, reusing a single list instead of allocating and building
tuples is *much* faster.

>     * starmap() - How does it differ from imap() and map()?

for computing a operator.pow,

if your data looks like this:  b=[2,3,5]  p=[3,5,7],
then use imap(operator.pow, a, b)

OTOH, if your data looks like this: c =[(2,3), (3,5), (5,7)],
then use starmap(operator.pow, c)

Essentially, it's the difference between f(a,b) and f(*c).


>     * times() - Why not declare times to take an optional argument to be
>       returned?

The use case is for looping when you don't care about the value:

    for i in itertools.times(3):
               print "hello"

>  (In general, it seems like count(), repeat() and times()
>       overlap heavily.  Examples of their usage might be helpful in
>       understanding when to use them, or at least when they are commonly
>       used in their Haskell/SML roots environments.)

Yes. I opted for using the atomic combinable building blocks
rather than constructing the more elaborate things like tabulate(f)
which can easily be made from the basic pieces:  imap(f,count())

I'll add more examples so that the usage becomes more obvious.


Thanks again for the review.


Raymond

#################################################################
#################################################################
#################################################################
#####
#####
#####
#################################################################
#################################################################
#################################################################