import itertools itertools.cycle(iterable)
iterable
- итерируемая последовательность.Функция cycle()
модуля itertools
создает бесконечный итератор, возвращающий элементы из итерируемой последовательности iterable
и сохраняющий копию каждого элемента. Когда последовательность iterable
исчерпана, начинает возвращать элементы из сохраненной копии.
Функция itertools.cycle(iterable)
примерно эквивалентна следующему коду:
# аргументу передается итератор # как мы знаем - итератор конечен def cycle(iterable): # cycle('ABCD') --> A B C D A B C D A B C D ... saved = [] for element in iterable: yield element saved.append(element) while saved: for element in saved: yield element
В коде выше, в функцию передается итерируемая последовательность
iterable
(может быть список, кортеж, ИТЕРАТОР и т.д.). Из протокола итератора видно, что они конечны (т.е. после прохождения по итератору, он остается пустым), по этому сначала создается списокsaved
, а потом, на основе полученного списка создается бесконечный цикл. Да, можно сразу создать список, вызвавlist(iterable)
, но что будет, если последовательность огромная? По этому список создается в режиме генератора (выражениеyield
).
Если не учитывать передачу итератора в качестве аргумента, то эквивалентный код сокращается до:
def cycle(list): # cycle('ABCD') --> A B C D A B C D A B C D ... while list: for element in list: yield element
Обратите внимание, что для выполнения функции itertools.cycle()
может потребоваться значительное вспомогательное хранилище для хранения копии в зависимости от длины итерируемой последовательности iterable
.
>>> from itertools import cycle >>> x = list(range(5)) >>> x # [0, 1, 2, 3, 4] >>> for i, j in enumerate(cycle(x)): ... print(j, end=' ') ... if i > 13: ... print() ... break ... # 0 1 2 3 4 0 1 2 3 4 0 1 2 3 4