Рассмотрим одну страшную конструкцию в Python 3.3+. Для начала напомним, генератор – это объект, который можно проитерировать только однажды. Записывается так:
def gen(): for x in range(100): yield x # Или покороче вот так f = (x for x in range(100))
Когда всего лишь один генератор – всё хорошо. Используем его как итератор и радуемся. Но не редки ситуации, в которых есть несколько генераторов:
gen_1 = (x for x in range(5)) gen_2 = (x for x in range(5, 10))
И стоит задача – проитерировать сначала один генератор, потом второй. Но вернуть значения не в виде списка, а в виде нового генератора.
Здесь на помощь приходит следующая конструкция: yield from <expr>, где <expr> — выражение, вычисление которого даёт итерируемый объект, из которого и вычленяется итератор.
Используя yield form, поставленная выше задача решается так:
def generator(): yield from gen_1 yield from gen_2 gen = generator()
И теперь можно просто проитерироваться по полученному генератору, в итоге получив результаты обоих первоначальных генераторов. Воспользуемся генератором списка, работа которого показана в предыдущем посте.
result = [n for n in gen] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]