1. ホーム
  2. python

[解決済み] コルーチン vs 継続 vs ジェネレータ

2022-04-27 06:35:25

質問

コルーチン、継続、ジェネレータの違いは何ですか?

どのように解決するのですか?

まず、最も単純なケースであるジェネレータから説明します。zvolkov が言ったように、ジェネレータは繰り返し呼び出すことができる関数/オブジェクトで、呼び出されると値を返して(yield)、実行を一時停止します。再び呼び出されると、最後に実行を中断したところから起動し、再び実行を行います。

ジェネレーターは、本質的には、(非対称の)コルーチンを切り詰めたものです。コルーチンとジェネレーターの違いは、コルーチンは最初に呼び出された後に引数を受け付けることができるのに対し、ジェネレーターは引数を受け付けることができない点です。

コルーチンを使った簡単な例を思いつくのはちょっと難しいのですが、ここでは私のベスト・トライを紹介します。このPythonのコードを例にしてみましょう。

def my_coroutine_body(*args):
    while True:
        # Do some funky stuff
        *args = yield value_im_returning
        # Do some more funky stuff

my_coro = make_coroutine(my_coroutine_body)

x = 0
while True:
   # The coroutine does some funky stuff to x, and returns a new value.
   x = my_coro(x)
   print x

コルーチンが使われる例として、レキサーとパーサーがあります。コルーチンが言語内にないか、何らかの方法でエミュレートされていない場合、レキシングとパーシングのコードは、実際には2つの別々の関心事であるにもかかわらず、一緒に混在させる必要があるのです。しかし、コルーチンを使えば、レキシングとパーシングのコードを分離することができるのです。

(対称型コルーチンと非対称型コルーチンの違いについては、これから説明します。また、非対称コルーチンはジェネレータに最も似ており、理解しやすい。私は、Pythonで非対称コルーチンを実装する方法の概要を説明しました)。

コンティニュエーションは、実はとてもシンプルな生き物なんです。プログラムの別のポイントを表す関数で、それを呼び出すと、その関数が表すポイントに自動的に実行が切り替わるだけです。あなたは毎日、気づかないうちに、非常に限定されたバージョンを使っているのです。例えば、例外は一種のインサイドアウトの継続と考えることができる。Pythonをベースにした継続の疑似コードの例をあげます。

Pythonに callcc() この関数は2つの引数を取り、1つ目は関数、2つ目は関数を呼び出すための引数のリストです。この関数の唯一の制限は、最後に受け取る引数が関数であることです(これは私たちの現在の継続になります)。

def foo(x, y, cc):
   cc(max(x, y))

biggest = callcc(foo, [23, 42])
print biggest

どうなるかというと callcc() は順番に foo() を、現在の継続時間 ( cc )、つまり、プログラム中のどの地点で callcc() が呼び出されました。このとき foo() は現在の継続を呼び出すので、本質的には callcc() を呼び出すと、スタックをロールバックして現在の継続が作成された場所、つまり、あなたが callcc() .

この結果、私たちの仮想的な Python バリアントは、次のように表示します。 '42' .

私の説明はかなり改善できるはずです!お役に立てれば幸いです。