Python 3000, zip, *args and iterators

Raymond Hettinger python at
Wed Dec 29 21:07:40 CET 2004

[Steven Bethard]  I'm just suggesting that in a function with a
> *args in the def, the args variable be an iterator instead of
> a tuple.

So people would lose the useful abilities to check len(args) or extract
an argument with args[1]?

Besides, if a function really wants an iterator, then its signature
should accept one directly -- no need for the star operator.

> > Likewise, he considers zip(*args) as a
> > transpose function to be an abuse of the *arg protocol.
> Ahh, I didn't know that.  Is there another (preferred) way to do

I prefer the abusive approach ;-) however, the Right Way (tm) is
probably nested list comps or just plain for-loops.  And, if you have
numeric, there is an obvious preferred approach.

>  So basically what I've done here is to
> "transpose" (to use your word) the iterators, apply my function, and
> then transpose the iterators back.

If you follow the data movements, you'll find that iterators provide no
advantage here.  To execute transpose(map(f, transpose(iterator)), the
whole iterator necessarily has to be read into memory so that the first
function application will have all of its arguments present -- using
the star operator only obscures that fact.

Realizing that the input has to be in memory anyway, then you might as
well take advantage of the code simplication offered by indexing:

>>> def twistedmap(f, iterable):
...     data = list(iterable)
...     rows = range(len(data))
...     for col in xrange(len(data[0])):
...         args = [data[row][col] for rows in rows]
...         yield f(*args)

Raymond Hettinger

More information about the Python-list mailing list