[Python-Dev] PEP 479: Change StopIteration handling inside generators

Steven D'Aprano steve at pearwood.info
Fri Nov 21 16:58:00 CET 2014


On Sat, Nov 22, 2014 at 12:53:41AM +1100, Chris Angelico wrote:
> On Sat, Nov 22, 2014 at 12:47 AM, Raymond Hettinger
> <raymond.hettinger at gmail.com> wrote:
> > Also, the proposal breaks a reasonably useful pattern of calling
> > next(subiterator) inside a generator and letting the generator terminate
> > when the data stream  ends.  Here is an example that I have taught for
> > years:
> >
> >     def izip(iterable1, iterable2):
> >         it1 = iter(iterable1)
> >         it2 = iter(iterable2)
> >         while True:
> >             v1 = next(it1)
> >             v2 = next(it2)
> >             yield v1, v2
> 
> Is it obvious to every user that this will consume an element from
> it1, then silently terminate if it2 no longer has any content?

"Every user"? Of course not. But it should be obvious to those who think 
carefully about the specification of zip() and what is available to 
implement it.

zip() can't detect that the second argument is empty except by calling 
next(), which it doesn't do until after it has retrieved a value from 
the first argument. If it turns out the second argument is empty, what 
can it do with that first value? It can't shove it back into the 
iterator. It can't return a single value, or pad it with some sentinel 
value (that's what izip_longest does). Since zip() is documented as 
halting on the shorter argument, it can't raise an exception. So what 
other options are there apart from silently consuming the value?

Indeed that is exactly what the built-in zip does:

py> a = iter("abcdef")
py> b = iter("abc")
py> list(zip(a, b))
[('a', 'a'), ('b', 'b'), ('c', 'c')]
py> next(a)
'e'


-- 
Steven


More information about the Python-Dev mailing list