11

I just read PEP0492 talking about the new approach on coroutines but the PEP failed to make me understand the difference between generator-based coroutines and native ones. Can someone tell me the difference (maybe with examples)?

For what I understood they uses different words (yield/yield from and await/async/yield). I understand that at the end of a native coroutine a yield is expected, but this also stands true for generator-based ones.

Daniel Mahler
  • 7,653
  • 5
  • 51
  • 90
Koldar
  • 1,317
  • 15
  • 35
  • 1
    The difference is the syntax; it is syntactic sugar to make it clearer and cleaner. – Martijn Pieters Sep 15 '15 at 09:35
  • So, apart from the syntax, they are identical? Sound too strange... it wouldn't be approved in a PEP. – Koldar Sep 16 '15 at 06:38
  • 1
    Decorators are syntactic sugar too, you could just use `func = decorator(func)` *after* the function declaration. Context managers are syntactic sugar for `try:...except:...finally:`. Python is all about readability and clarity of purpose, this fits right in with those goals. – Martijn Pieters Sep 16 '15 at 08:35
  • Putting it in that way, it seems more legit. Make an answer and I'll accept it – Koldar Sep 16 '15 at 09:14

3 Answers3

11

To expand on what Mike S wrote: native coroutines in CPython share most of the same code as generators, so there's little functional difference. However, I think that PEP-492 rises above the threshold of just "syntactic sugar". Generators and native coroutines have separate purposes, so the new syntax clarifies an author's intent and can do things the old syntax cannot. Here are some examples:

  • Generators are iterable, and native coroutines are not.
  • Native coroutines also permit new syntaxes like async context managers and async iterators.
  • Coroutines have useful debugging messages, e.g. a warning if you never await a coroutine object.

The new syntax also nicely mirrors the asyncio library and resembles keywords used in other languages.

Mark E. Haase
  • 25,965
  • 11
  • 66
  • 72
  • 1
    [https://docs.python.org/3/reference/expressions.html#yield-expressions) is, and always has been, an expression `await` cannot be used in any places `yield from` can't. In fact, the difference is the exact opposite: `yield from` can be used in places `await` can't—namely, non-`async` functions (and that restriction occasionally helps catch errors). – abarnert May 04 '18 at 01:17
  • Thanks @abarnert. You are definitely right. I have removed that incorrect statement from my answer. – Mark E. Haase Jun 28 '18 at 14:04
  • @MarkE.Haase am I going to be right saying that native coroutines behind the scenes are based on generators? – EngineerSpock Apr 09 '20 at 13:41
  • @EngineerSpock Yes – Mark E. Haase Apr 09 '20 at 14:25
4

There is no functional difference. "Native coroutines" using the async and await keywords are just syntactic sugar for what was previously implemented in "generator-based coroutines."

The use of async and await is recommended in the 3.5 docs if there is no need to support older Python versions.

Mike S
  • 935
  • 2
  • 6
  • 18
0

Well, conventionally the way to write coroutines involved callbacks. Even though callbacks might be convenient initially, but in my opinion, they lead to highly complicated and complex code, which is not pythonic to say the least. Besides, yield (especially yield from since python 3.3), has made implementing coroutines a lot easier and pythonic.

With generators, you can easily divide your code into initial part and callbacks.

@asyncio.coroutine
def print_sum(x, y):
    result = yield from compute(x, y)

    #write callback code
    print("%s + %s = %s" % (x, y, result))
hspandher
  • 15,934
  • 2
  • 32
  • 45