ソフトな忘却力(111) PythonのGeneratorとsend()で双方向通信?

Joseph Halfmoon

「サイエンティフィックPythonのための」IDE、Spyder上にてScientific Python Lecturesの実習中。前回はitertoolsの自主練習でした。今回は、send()つかったGeneratorとの「双方向通信」です。あれ、そんな機能あったっけ?素人老人は使った記憶がありません。忘却力で忘れたのか?いやそんなことはあるまい。

※「 ソフトな忘却力」投稿順 Index はこちら

Scientific Python Lectures様のコースは例題だけでなく、エクササイズなども充実、それを全部順番に解いていったら必ずや立派な人になれるだろ~と思います。でも老い先短い年寄には量が多過ぎて多分死ぬまでに終わりません。適当な練習でお茶を濁してます。今回は「7. Advanced Python Constructs」の「7.1.4 Bidirectional communication」です。

PEP 342 – Coroutines via Enhanced Generators

今回練習するレクチャの「7.1.4 Bidirectional communication」は、PythonのPEP342で拡張された機能を使って、Generator関数と「通信」をするものです。PEP342以前、Generatorをnext()で呼び出して次々と値を得ることはできたものの、その値の生成過程に外から介入したり、あるいはGeneratorそのものを余計なものを残さぬように滅するような操作は定義されていなかったようです。どうもGeneratorをコルーチンらしいコルーチンとして使えるようにするために提案されたのが、PEP342みたいっす。 知らんけど。PEP342へのリンクが以下に。

PEP 342 – Coroutines via Enhanced Generators

今回実験のスクリプト

今回は、初期値と公差の2つを与えて生成すると、呼び出す度に等差数列の項を1個づつ返してくれるジェネレータを作ってみます。初期値1、公差1なら

1、2、3、4

という感じ。しかし、呼び出すときにnext()ではなく、send()を使って呼び出し側からジェネレータ側に値を送信してやると、公差を変更できるっと。公差2にしたら、こんな感じ。

6、8、10、12

さて実際に動作確認したスクリプトが以下に。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thr Jul 30 2025

@author: jhalfmoon
Generator send() example
"""
def ArithProgression(vinit, cdiff):
    v = vinit
    diff = cdiff
    while True:
        temp = (yield v)
        if temp is not None:
           diff = temp
        v = v + diff

def main():
    aprog = ArithProgression(1, 1)
    print("Common Diff:1", [next(aprog) for _i in range(5)])
    print("Common Diff:Change 1->2", [aprog.send(2)])
    print("Common Diff:2",[next(aprog) for _i in range(5)])
    
if __name__ == '__main__':
    main()

上記を実行した結果が以下に。pythonArithmeticProgression

確かに公差を変更できたみたい。

しかしね、コルーチンと言えば、ジェネレータ以外にもコルーチンを実現するための仕組み asyncio とかあったんじゃなかったっけ。別シリーズの過去回で asyncio 使っている回が以下に。

IoT何をいまさら(79) Python, threadingとasyncioなLチカ

まあ、おこのみってことで? いい加減だな。

ソフトな忘却力(110) Pythonのitertools、ちょこっと自主練習 へ戻る

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です