(original) (raw)
On May 5, 2015 2:14 PM, "Guido van Rossum" <guido@python.org> wrote:
\>
\> In the PEP 492 world, these concepts map as follows:
\>
\> - Future translates to "something with an \_\_await\_\_ method" (and asyncio Futures are trivially made compliant by defining Future.\_\_await\_\_ as an alias for Future.\_\_iter\_\_);
\>
\> - "asyncio coroutine" maps to "PEP 492 coroutine object" (either defined with \`async def\` or a generator decorated with @types.coroutine -- note that @asyncio.coroutine incorporates the latter);
\>
\> - "either of the above" maps to "awaitable".Err, aren't the first and third definitions above identical?
Surely we want to say: an async def function is a convenient shorthand for creating a custom awaitable (exactly like how generators are a convenient shorthand for creating custom iterators), and a Future is-an awaitable that also adds some extra methods.
The current PEP 492 proposal does endow the object returned by calling an async function (let's call it a coroutine object) with an __await__ method. And there's a good reason for this -- the bytecode generated for await treats coroutine objects special, just like the bytecode generated for yield-from treats generator objects special. The special behavior they have in common is the presence of send() and throw() methods, which are used to allow send() and throw() calls on the outer generator to be passed into the inner generator with minimal fuss. (This is the reason why "yield from X" is *not* equivalent to "for x in X: yield x".)