コルーチンは send, throw, close メソッドで外部から制御できます。これらを使うと、双方向通信やエラーハンドリングが可能になります。
send:値を送り込む
yield 式は値を受け取れます。send で値を渡すと、yield 式の評価結果になります。
def accumulator(): total = 0 while True: value = yield total if value is None: break total += value coro = accumulator() next(coro) # ジェネレータを起動(最初の yield まで進む) print(coro.send(10)) # 10 print(coro.send(20)) # 30 print(coro.send(5)) # 35
最初の next() は send(None) と同等で、ジェネレータを最初の yield まで進めます。
throw:例外を投入する
throw でコルーチン内部に例外を発生させられます。
def coro_with_error_handling(): try: while True: value = yield print(f"Received: {value}") except ValueError as e: print(f"Error handled: {e}") yield "recovered" c = coro_with_error_handling() next(c) c.send(1) # Received: 1 result = c.throw(ValueError, "something wrong") print(result) # recovered
close:コルーチンを終了する
close は GeneratorExit を投入してコルーチンを終了させます。
def resource_manager(): print("Acquiring resource") try: while True: yield finally: print("Releasing resource") c = resource_manager() next(c) # Acquiring resource c.close() # Releasing resource
finally ブロックでクリーンアップ処理が実行されます。
状態マシンの実装例
def state_machine(): state = "IDLE" while True: event = yield state if state == "IDLE" and event == "start": state = "RUNNING" elif state == "RUNNING" and event == "stop": state = "IDLE" sm = state_machine() print(next(sm)) # IDLE print(sm.send("start")) # RUNNING print(sm.send("stop")) # IDLE
send, throw, close を活用すると、コルーチンを協調的なタスクとして柔軟に制御できます。