Ответ
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.