Конструкция yield from

Рассмотрим одну страшную конструкцию в 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]