Coroutine vs kontynuacja vs Generator
Jaka jest różnica między koroutinem a kontynuacją i generatorem ?
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!
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ść.
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ć.
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