yield from は、別のイテラブルやジェネレータの要素をすべて委譲して yield するための構文です。ネストしたジェネレータを扱う際にコードを簡潔にできます。
yield from の基本
yield from を使うと、イテラブルの各要素を順番に yield できます。
def generator(): yield from [1, 2, 3] yield from "ABC" for value in generator(): print(value) # 1, 2, 3, A, B, C
yield from を使わない場合との比較
yield from がない場合、for ループを書く必要があります。
yield from を使う
yield from iterable
コードが簡潔になる
for ループを使う
for item in iterable:
yield item
冗長になる
# yield from なし def flatten_without(): for item in [1, 2, 3]: yield item for item in [4, 5, 6]: yield item # yield from あり def flatten_with(): yield from [1, 2, 3] yield from [4, 5, 6]
ネストしたリストのフラット化
yield from の典型的な使い方は、入れ子になった構造をフラットにすることです。
def flatten(nested): for item in nested: if isinstance(item, list): yield from flatten(item) # 再帰的に委譲 else: yield item nested = [1, [2, 3, [4, 5]], 6, [7]] print(list(flatten(nested))) # [1, 2, 3, 4, 5, 6, 7]
サブジェネレータへの委譲
yield from は別のジェネレータに処理を委譲する際にも使います。
def sub_generator(): yield "sub 1" yield "sub 2" return "サブ完了" def main_generator(): yield "main 開始" result = yield from sub_generator() print(f"受け取った値: {result}") yield "main 終了" for value in main_generator(): print(value) # main 開始 # sub 1 # sub 2 # 受け取った値: サブ完了 # main 終了
サブジェネレータの return 値は、yield from 式の結果として受け取れます。
複数のデータソースを連結
複数のイテラブルを順番に処理するジェネレータを簡単に作れます。
def chain(*iterables): for it in iterables: yield from it result = list(chain([1, 2], "ab", (10, 20))) print(result) # [1, 2, 'a', 'b', 10, 20]
注意点
yield from は、サブジェネレータが StopIteration を送出するまで、すべての値を委譲します。途中で制御を戻すことはできないため、条件付きで中断したい場合は通常の for ループと yield を組み合わせてください。