Понимание zip-функции

Все обсуждения посвящены python 3.1.2; см. Документы Python для источника моего вопроса.

Я знаю, что делает zip; Я просто не понимаю, почему это можно реализовать следующим образом:

def zip(*iterables):
    # zip('ABCD', 'xy') --> Ax By
    iterables = map(iter, iterables)
    while iterables:
        yield tuple(map(next, iterables))

Скажем, я называю zip(c1, c2, c3). Если я правильно понял, итерации - это исходный код (c1, c2, c3).

Линия iterables = map(iter, iterables) преобразует ее в итератор, который будет возвращать iter (c1), iter (c2), iter (c3), если он повторяется.

Внутри цикла map(next, iterables) - это итератор, который возвратит next(iter(c1)), next(iter(c2)) и next(iter(c3)), если будет выполнено повторение. Вызов tuple преобразует его в (next(iter(c1)), next(iter(c2)), next(iter(c3)), исчерпывая его аргумент (iterables) на самом первом вызове, насколько я могу судить. Я не понимаю, как цикл while удается продолжить, если он проверяет iterables; и если он продолжает, почему вызов tuple не возвращает пустой кортеж (итератор исчерпан).

Я уверен, что мне не хватает чего-то очень простого.

Ответ 1

Похоже, это ошибка в документации. "Эквивалентный" код работает в python2, но не в python3, где он переходит в бесконечный цикл.

И последняя версия документации имеет ту же проблему: http://docs.python.org/release/3.1.2/library/functions.html

Похоже на изменение 61361, поскольку он объединил изменения с python 2.6 без проверки того, что они были правильными для python3.

Похоже, что проблема не существует в наборе документации транка, но вы, вероятно, должны сообщить об ошибке в http://bugs.python.org/.

Ответ 2

Кажется, что этот код должен быть прочитан как код python-2.x. Он даже не работает должным образом в py3k.

Что происходит в python-2.x, так это то, что map возвращает список итераторов, когда вызывается next, возвращает элемент итератора, причем эти элементы объединены в кортеж. Итак, учитывая

>>> zip('ABCD', 'xy')

iterables - это список из 2 итераторов, на каждой итерации в цикле while используется следующий (первый оставшийся) элемент итератора (''A' и 'x' и т.д.) и выводится как элемент кортежа, то после того, как будут получены последние элементы, (на третьей итерации), поднятый StopIteration, остановит генератор. while iterables всегда остается True.