Ответ
yield from <iterable>
— это синтаксическая конструкция, которая позволяет одному генератору делегировать часть своих операций другому генератору или любому итерируемому объекту. Она напрямую передает управление и значения между вызывающим кодом и вложенным генератором (подгенератором).
Проблема, которую решает yield from
:
Без этой конструкции для итерации по вложенному генератору пришлось бы писать громоздкий цикл.
# Без yield from
def chain_iterables(iter1, iter2):
for value in iter1:
yield value
for value in iter2:
yield value
print(list(chain_iterables(range(3), "ABC")))
# Вывод: [0, 1, 2, 'A', 'B', 'C']
Решение с yield from
:
Код становится значительно чище и декларативнее.
# С yield from
def chain_with_yield_from(iter1, iter2):
yield from iter1
yield from iter2
print(list(chain_with_yield_from(range(3), "ABC")))
# Вывод: [0, 1, 2, 'A', 'B', 'C']
Основные преимущества:
- Краткость и читаемость: Заменяет вложенный цикл
for ... yield
, делая намерение очевидным. - Производительность: Делегирование происходит на уровне интерпретатора, что эффективнее ручного перебора в Python-коде.
- Двусторонняя связь:
yield from
не только получает значения, но и пробрасывает вызовы.send()
,.throw()
и.close()
напрямую в подгенератор. Это критически важно для продвинутых сценариев использования генераторов, включая корутины. - Основа для
async/await
: Механизмawait
в асинхронных функциях построен на тех же принципах делегирования, что иyield from
.