155

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

4

3 に答える 3

133

ジェネレーターから始めましょう。ジェネレーターが最も単純なケースであるためです。@zvolkovが述べたように、これらは返さずに繰り返し呼び出すことができる関数/オブジェクトですが、呼び出されると値を返し(生成)、実行を一時停止します。彼らが再び呼び出されると、彼らは最後に実行を中断したところから起動し、再び彼らのことをします。

ジェネレーターは、本質的にはカットダウンされた(非対称の)コルーチンです。コルーチンとジェネレーターの違いは、コルーチンは最初に呼び出された後に引数を受け入れることができるのに対し、ジェネレーターは受け入れることができないことです。

コルーチンを使用する場所の簡単な例を思い付くのは少し難しいですが、これが私の最善の試みです。この(構成された)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'

それがお役に立てば幸いです。私の説明はかなり改善されると確信しています。

于 2009-04-03T22:05:22.870 に答える
34

コルーチンは、順番にジョブを実行し、一時停止してグループ内の他のコルーチンに制御を渡すいくつかのプロシージャの 1 つです。

継続は、ある手続きに渡す「関数へのポインタ」であり、その手続きが完了したときに実行されます (「継続」)。

ジェネレーター (.NET 内) は、値を吐き出し、メソッドの実行を「一時停止」し、次の値を求められたときに同じポイントから続行できる言語構造です。

于 2009-04-03T21:29:25.453 に答える
10

新しいバージョンのPythonでは、を使用して値をジェネレーターに送信できますgenerator.send()。これにより、Pythonジェネレーターは効果的にコルーチンになります。

Pythonジェネレーターと他のジェネレーター(グリーンレットなど)の主な違いは、Pythonではyield value呼び出し元にしか戻れないことです。グリーンレットにいる間target.switch(value)、特定のターゲットコルーチンに移動し、targetが実行され続ける値を生成できます。

于 2011-08-31T02:51:31.927 に答える