[Python-3000] Parallel iteration syntax

Michael Chermside mcherm at mcherm.com
Tue Mar 28 15:54:12 CEST 2006


Greg Ewing writes:
> Some years ago there was a long discussion about extending
> the for-loop to express parallel iteration over a number
> of iterables
        [...]
> I'm mentioning it here again just in case anyone wants
> to consider it for Py3k. I still believe it would be
> nice to have a direct syntax for parallel iteration
> to avoid the overhead of using zip or iterzip.

There's one big problem I see with this. Parallel iteration
is underspecified... there are several reasonable choices
for what to do if the iterables are of differing length.

  (1) Fill out the short iterables with "None" elements.
  (2) Stop as soon as any iterable runs out.
  (3) Raise an exception if the iterables are not all
      the same length.

Today, we support these with different idioms:

   (1)
   result = map(some_func, seq_x, seq_y)

   (2)
   for x, y in zip(seq_x, seq_y):
      some_func(x, y)

   (3)
   # all right, there's no common idiom I know of for
   # (3), but there ought to be, because it is probably
   # what the programmer wants most often, since the
   # most common case is where you are expecting the
   # lists to be the same length.

Frankly, I have no interest in supporting (1)... it's not
really natural. But both (2) and (3) have some good points.
(2) is fundamentally more powerful (it can do things that
(3) can't), while (3) is probably what programmers need
most often; it has the advantage of being explicit about
errors and it is difficult to simulate.

So which to support?

-- Michael Chermside


PS: To be explicit, what I mean by (3) is this:

def equizip(*iterables):
    iterators = [iter(x) for x in iterables]
    while True:
        try:
            first_value = iterators[0].next()
            try:
                other_values = [x.next() for x in iterators[1:]]
            except StopIteration:
                raise IterableLengthMismatch
            else:
                values = [first_value] + other_values
                yield tuple(values)
        except StopIteration:
            for iterator in iterators[1:]:
                try:
                    extra_value = iterator.next()
                except StopIteration:
                    pass # this is what we expect
                else:
                    raise IterableLengthMismatch
            raise StopIteration

for x, y in equizip(seq_x, seq_y):
    some_func(x, y)



More information about the Python-3000 mailing list