40. Бесконечный генератор для итерируемого объекта
Условие задачи:
Написать бесконечный генератор, который принимает любой итерируемый объект и по кругу возвращает его элементы без завершения.
Пример:
# [1, 2, 3] -> 1, 2, 3, 1, 2, 3, ...
from typing import Iterable
def my_gen(inp_value: Iterable):
...
Спойлеры к решению
Подсказки
- Нужна функция-генератор, значит внутри должен быть
yield. - Нужно пройти по переданному итерируемому объекту.
- После последнего элемента генератор должен снова начать с первого.
- Для этого можно использовать бесконечный цикл
while True. - Чтобы можно было повторно проходить по данным, входной объект лучше сохранить в
tupleилиlist. - Если передан пустой итерируемый объект, бесконечно возвращать нечего.
Решение
from typing import Iterable, Iterator, TypeVar
T = TypeVar("T")
def my_gen(inp_value: Iterable[T]) -> Iterator[T]:
values = tuple(inp_value)
if not values:
return
while True:
for item in values:
yield item
Пример использования:
gen = my_gen([1, 2, 3])
for _ in range(10):
print(next(gen), end=" ")
Результат:
1 2 3 1 2 3 1 2 3 1
Функция сначала сохраняет элементы входного итерируемого объекта в tuple:
values = tuple(inp_value)
Это нужно, чтобы по элементам можно было проходить снова и снова. Затем запускается бесконечный цикл:
while True:
Внутри него функция каждый раз проходит по сохранённым значениям и отдаёт элементы через yield.
Альтернативный короткий вариант через стандартную библиотеку:
from itertools import cycle
from typing import Iterable, Iterator, TypeVar
T = TypeVar("T")
def my_gen(inp_value: Iterable[T]) -> Iterator[T]:
return cycle(inp_value)
itertools.cycle() делает то же самое: бесконечно возвращает элементы итерируемого объекта по кругу.