コルーチンは基本的に、特定の時点で実行を一時停止/中断できる関数であり、後でいつでも同じ時点から実行を再開できます。

チェックポイントを挿入し、ここで関数の実行を一時停止し、呼び出し元のポイントに制御を戻すことをプログラムに伝えるメカニズム、またはより正確にはキーワードが必要です。 いつでも実行を再開します。

Pythonでは、yieldキーワードを使用して関数の実行を一時停止することができます。

だからここで物事が面白くなる場所です:

  • コルーチンは、実行が一時停止され、制御が呼び出されたポイントに返される1つ以上のチェックポイントを持つ関数と考えることができます。
  • 本質的に、コルーチンは多くの部分に分割された関数であり、next関数を使用してforループの各反復を実行すると、コルーチンの各部分を実行できます。

ここに基本的な例があります:

OUTPUT :<class 'generator'>
Function Starts
Function Ends

出力から、私たちはいくつかのことに気づきます:

  • まず、ジェネレータオブジェクトを与えるコルーチン/関数を呼び出す必要があります。
  • そのジェネレータオブジェクトはイテレータと同様に動作しますが、イテレータの場合はiterableをトラバースしています。 ジェネレータでは、コルーチンの一部を実行しています。
  • forループの背後でStopIteration例外がスローされてキャッチされるのと同じように、この場合もコルーチンの最後の部分が実行されたときに同じことが起こります。

今、この間の関数の一時停止は非常に興味深いものであり、いくつかの可能性を開きます:

  • 関数が一時停止されたとき、私たちは何もしません。
  • 変数が関数内で何度か変更されていて、特定のチェックポイントでその特定の変数の値が必要だとします。 次に、その特定のチェックポイントでその関数を一時停止すると、その変数の値が返されます。

例を見てみましょう:

OUTPUT :Function Part 1
5
Function part 2
12
Function part 3

ここで、xの値は、関数の実行が一時停止されているため、異なるチェックポイントでyieldによって返されます。

関数の最後の部分を実行していて、関数にyieldが残っていないときはいつでも、その最後の部分を実行した後、StopIteration例外が発生します。

イテレータが次の関数を実行しようとしたときと同じように、iterableに要素が残っていない場合は、StopIteration例外も発生します。

  • 特定のチェックポイント(つまり、関数の特定の状態)で値(定数または変数にすることができます)を送信したいとします。 また、yieldキーワードを使用してそれを行うこともできます。 値を送信する場合は、nextの代わりにsend関数を使用します。

例を見てみましょう:

OUTPUT :Function part 1
6
Function part 2
12
Function part 3

sendを使用する前にnextを使用した理由は、yieldチェックポイントにいて、yieldが式の右側にあるときにのみsendを使用できるためです。 そのため、最初のyieldに到達するには、next関数を使用する必要があります。

ここで興味深いコルーチンのアプリケーションが登場します。 マルチスレッドで行うように、2つの関数を前後に切り替えたいとします。 マルチスレッドでは、OSがinterruptに遭遇するまで、実行を続けます。 この場合、いつでも切り替えることができます。

例を見てみましょう:

OUTPUT :Function 1 part 1
Function 2 part 1
Function 1 part 2
Function 1 part 3
Function 2 part 2
Function 2 part 3
Function 2 part 4
Function 1 part 4
Function 1 part 5

この例では、必要に応じてコルーチンを前後に切り替えることができることがわかります。

複数のコルーチン間の切り替えを処理する独自のカスタムスケジューラを書くと、マルチスレッドで行うことをシングルスレッドで実現できます。

コルーチンには並行性などの多くのアプリケーションがあり、ネットワークプログラミングにおけるプロデューサー-コンシューマーやセンダ-レシーバのような他のプログラミングパターンも実装することができる。 私は今後の記事でそれらを探索することになります。

コルーチンは、asyncio、twisted、aiohttpなどの多くのフレームワークの構成要素でもあります。 それらはまたパイプラインを作り、問題を解決するために一緒に鎖でつなぐことができます。