Coroutine vs kontynuacja vs Generator

Jaka jest różnica między koroutinem a kontynuacją i generatorem ?

Author: Benson, 2009-04-04

3 answers

Zacznę od generatorów, bo to najprostsza sprawa. Jak wspomniał @zvolkov, są to funkcje / obiekty, które mogą być wielokrotnie wywoływane bez zwracania, ale po wywołaniu zwrócą (zwrócą) wartość, a następnie zawieszą ich wykonanie. Kiedy zostaną wezwani ponownie, zaczną od miejsca, w którym ostatnio zawieszono egzekucję i znowu zrobią swoje.

Generator jest zasadniczo ściętym (asymetrycznym) koroutinem. Różnica między korotynem a generatorem polega na tym, że coroutine może przyjmować argumenty po pierwszym wywołaniu, podczas gdy generator nie może.

To trochę trudne do niektórych z trywialnym przykładem, gdzie można użyć coroutines, ale oto moja najlepsza próba. Weźmy ten (zmyślony) Kod Pythona jako przykład.

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

Przykładem zastosowania koroutinów są lexery i parsery. Bez corutines w języku lub emulowane w jakiś sposób, lexing i parsing kod musi być zmieszany ze sobą, nawet jeśli są one naprawdę dwa oddzielne obawy. Ale używając koroutine, możesz oddzielić kod lexingu i parsingu.

(zamierzam pominąć różnicę między symetrycznymi i asymetrycznymi koroutinami. Wystarczy powiedzieć, że są równoważne, można konwertować z jednego do drugiego, a asymetryczne koroutiny-które są najbardziej podobne do generatorów-są łatwiejsze do zrozumienia. Opisywałem, jak można zaimplementować asymetryczne koroutiny w Pythonie.)

Kontynuacje są właściwie dość prostymi bestiami. Wszystkie są to funkcje reprezentujące inny punkt w programie, który, jeśli go wywołasz, spowoduje automatyczne przełączenie wykonania do punktu, który reprezentuje funkcja. Używasz ich bardzo ograniczonych wersji każdego dnia, nawet nie zdając sobie z tego sprawy. Wyjątki, na przykład, można uznać za swego rodzaju inside-out kontynuację. Podam Ci pseudokod oparty na Pythonie przykład kontynuacji.

Powiedzmy, że Python miał funkcję o nazwie callcc() i ta funkcja miała dwa argumenty, pierwszy jest funkcją, a druga jest listą argumentów do wywołania. Jedynym ograniczeniem tej funkcji byłoby to, że ostatnim argumentem będzie funkcja (która będzie naszą bieżącą kontynuacją).

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

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

To, co się stanie, to to, że callcc() z kolei wywoła foo() z bieżącą kontynuacją (cc), czyli odniesieniem do punktu w programie, w którym callcc() został wywołany. Kiedy foo() wywoła bieżącą kontynuację, jest to zasadniczo to samo, co powiedzenie callcc() do Zwraca wartość, z którą wywołujesz bieżącą kontynuację, a gdy to zrobi, wywraca stos do miejsca, w którym została utworzona bieżąca kontynuacja, np. gdy wywołałeś callcc().

Rezultatem tego wszystkiego byłoby to, że nasz hipotetyczny wariant Pythona wydrukuje '42'.

Mam nadzieję, że to pomoże, i jestem pewien, że moje wyjaśnienie może zostać poprawione na sporo!

 109
Author: Keith Gaughan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-16 19:53:37

Coroutine jest jedną z kilku procedur, które na zmianę wykonują swoją pracę, a następnie zatrzymują się, aby dać kontrolę innym coroutinom w grupie.

Kontynuacja jest "wskaźnikiem do funkcji"przekazywanym do jakiejś procedury, która ma zostać wykonana ("continued with") po wykonaniu tej procedury.

Generator (w. NET) jest konstrukcją języka, która może wypluć wartość," wstrzymać " wykonanie metody, a następnie przejść z tego samego punktu, gdy zapytany o następną wartość.

 29
Author: zvolkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-07 22:35:12

W nowszej wersji Pythona można wysyłać wartości do generatorów za pomocą generator.send(), co sprawia, że generatory Pythona są efektywnie generowane.

Główna różnica między generatorem Pythona, a innym generatorem, powiedzmy greenletem, polega na tym, że w Pythonie twój {[1] } może wrócić tylko do wywołującego. Podczas gdy w greenlet, {[2] } może zabrać cię do określonego celu i dać wartość, w której target będzie nadal działać.

 8
Author: Yichuan Wang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-31 02:51:31