Coroutines są zasadniczo funkcjami, których wykonywanie może być wstrzymane/zawieszone w określonym punkcie, a następnie możemy wznowić wykonywanie z tego samego punktu później, kiedy tylko chcemy.

potrzebujemy mechanizmu-a dokładniej słowa kluczowego-za pomocą którego możemy wstawić punkt kontrolny i powiedzieć programowi, że chcemy wstrzymać wykonywanie funkcji i zwrócić kontrolę do punktu, z którego został wywołany. Wznowimy egzekucję, kiedy tylko będziemy chcieli.

w Pythonie możemy wstrzymać wykonywanie funkcji za pomocą słowa kluczowego yield.

więc tu się robi ciekawie:

  • możemy myśleć o coroutine jako funkcji, która ma jeden lub więcej punktów kontrolnych, gdzie wykonanie zostanie wstrzymane, a kontrola zostanie zwrócona do punktu, z którego została wywołana.
  • w istocie, coroutine jest funkcją podzieloną na wiele części i możemy wykonać każdą część coroutine tak jak wykonujemy każdą iterację pętli for używając funkcji next.

oto podstawowy przykład:

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

na wyjściu zauważamy kilka rzeczy:

  • najpierw musimy wywołać funkcję coroutine/, która da nam obiekt generatora.
  • ten obiekt generatora będzie zachowywał się podobnie do iteratora, ale w przypadku iteratora przemierzamy iterable. Z generatorem, wykonujemy części coroutine.
  • tak jak wyjątek StopIteration jest wyrzucany i łapany za kulisy pętli for, tak samo dzieje się w tym przypadku, gdy ostatnia część coroutine jest wykonywana.

teraz to wstrzymanie funkcji pomiędzy jest bardzo interesujące i otwiera kilka możliwości:

  • Kiedy funkcja jest wstrzymana, nic nie robimy, co właśnie widzieliśmy.
  • Załóżmy, że zmienna jest modyfikowana kilka razy w funkcji i chcemy, aby wartość tej konkretnej zmiennej znajdowała się w określonym punkcie kontrolnym. Następnie, kiedy zatrzymamy tę funkcję na danym punkcie kontrolnym, zwraca ona wartość tej zmiennej.

zobaczmy przykład:

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

tutaj wartość x jest zwracana przez yield w różnych punktach kontrolnych, ponieważ wykonywanie funkcji zostało wstrzymane.

ilekroć wykonujemy ostatnią część funkcji i nie ma w niej żadnego plonu, po wykonaniu tej ostatniej części zostanie wywołany wyjątek StopIteration.

podobnie jak kiedy iterator próbuje wykonać następną funkcję, ale nie ma już więcej elementów w iteraable, również podnosi wyjątek StopIteration.

  • Załóżmy, że chcemy wysłać wartość (która może być stała lub zmienna) w określonym punkcie kontrolnym (tzn. w określonym stanie funkcji). Możemy to również zrobić za pomocą słowa kluczowego yield. Gdy chcemy wysłać wartość, użyjemy funkcji send zamiast next.

zobaczmy przykład:

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

powodem, dla którego użyliśmy next przed użyciem send jest to, że możemy użyć send tylko wtedy, gdy znajdujemy się w punkcie kontrolnym yield, a yield znajduje się po prawej stronie wyrażenia. Aby dotrzeć do tego pierwszego yield, musimy użyć funkcji next.

teraz nadchodzi ciekawe zastosowanie coroutines. Załóżmy, że chcemy przełączać się między dwiema funkcjami, tak jak to robimy w wielowątkowości. W przypadku wielowątkowości, dopóki system operacyjny nie natknie się na interrupt, będzie on nadal wykonywany. W tym przypadku możemy przełączać się, kiedy tylko chcemy.

zobaczmy przykład:

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

w tym przykładzie widzimy, że możemy przełączać się tam iz powrotem między coroutines, kiedy tylko chcemy.

jeśli więc napiszemy własny, niestandardowy harmonogram, który obsługuje przełączanie między wieloma koronami, możemy osiągnąć za pomocą pojedynczego wątku to, co robimy z wielowątkowością.

Coroutines mają wiele aplikacji, takich jak współbieżność i inne wzorce programowania mogą być również zaimplementowane, jak producent-konsument lub nadawca-odbiornik w programowaniu sieciowym. Będę je badał w nadchodzących artykułach.

Coroutines są również budulcem wielu frameworków, takich jak asyncio, twisted, aiohttp. Można je również łączyć w łańcuchy, aby tworzyć rurociągi i rozwiązywać problemy.