Reputation: 52253
All discussion is about python 3.1.2; see Python docs for the source of my question.
I know what zip
does; I just don't understand why it can be implemented like this:
def zip(*iterables):
# zip('ABCD', 'xy') --> Ax By
iterables = map(iter, iterables)
while iterables:
yield tuple(map(next, iterables))
Let's say I call zip(c1, c2, c3)
. If I understand correctly, iterables is initially the tuple (c1, c2, c3).
The line iterables = map(iter, iterables)
converts it to an iterator that would return iter(c1), iter(c2), iter(c3) if iterated through.
Inside the loop, map(next, iterables)
is an iterator that would return next(iter(c1))
, next(iter(c2))
, and next(iter(c3))
if iterated through. The tuple
call converts it to (next(iter(c1)), next(iter(c2)), next(iter(c3))
, exhausting its argument (iterables
) on the very first call as far as I can tell. I don't understand how the while
loop manages to continue given that it checks iterables
; and if it does continue why the tuple
call doesn't return empty tuple (the iterator being exhausted).
I'm sure I'm missing something very simple..
Upvotes: 14
Views: 18430
Reputation: 53310
It looks like it's a bug in the documentation. The 'equivalent' code works in python2 but not in python3, where it goes into an infinite loop.
And the latest version of the documentation has the same problem: http://docs.python.org/release/3.1.2/library/functions.html
Looks like change 61361 was the problem, as it merged changes from python 2.6 without verifying that they were correct for python3.
It looks like the issue doesn't exist on the trunk documentation set, but you probably should report a bug about it at http://bugs.python.org/.
Upvotes: 9
Reputation: 319601
It seems like this code is supposed to be read as python-2.x code. It doesn't even run properly in py3k.
What happens in python-2.x is that map
return a list of iterators, when next
is called it returns an element of iterator, those elements combined into tuple. So, given
>>> zip('ABCD', 'xy')
iterables is a list of 2 iterators, on each iteration within the while loop, next (first remaining) element of iterator is consumed (''A'
and 'x'
, etc), and yielded as an element of a tuple, then after last elements are yielded, (on 3rd iteration) raised StopIteration
stops the generator. while iterables
always remains True
.
Upvotes: 7