On Wed, Nov 8, 2017 at 11:34 AM, Chris Angelico <ros...@gmail.com> wrote:
> On Thu, Nov 9, 2017 at 5:20 AM, Ian Kelly <ian.g.ke...@gmail.com> wrote:
>> On Wed, Nov 8, 2017 at 11:12 AM, Chris Angelico <ros...@gmail.com> wrote:
>>> Except that "yield from" is used by generators to delegate to other
>>> generators, and "await" is used by coroutines to delegate to other
>>> coroutines. In an asynchronous generator, "yield" produces values, and
>>> "yield from" would delegate to another asynchronous generator. They
>>> are NOT synonyms.
>>
>> Only because the devs have chosen to reserve the possibility of
>> asynchronous generators. Abstractly, coroutines and generators are
>> distinct concepts, but pragmatically, coroutines *are* generators.
>> Native coroutines don't actually change this; they just do a better
>> job of hiding it.
>
> Coroutines *are implemented using* generators. And I don't know what
> you mean by "reserve the possibility of"; asynchronous generators do
> exist:

They didn't exist when native coroutines were implemented. That's when
the possibility was reserved.

> PEP 525 https://www.python.org/dev/peps/pep-0525/ says:
> """
> While it is theoretically possible to implement yield from support for
> asynchronous generators, it would require a serious redesign of the
> generators implementation.
> """
>
> In other words, it's only because of *implementation details* that
> "yield from" inside a generator is difficult. There's no
> language-level reason for it to be forbidden, and there is absolutely
> NO correlation between "await" and "yield from" in an async function.

Since we're quoting PEPs, here's what PEP 492 says about "await":

https://www.python.org/dev/peps/pep-0492/#id56
"""
await, similarly to yield from, suspends execution of [the] coroutine
until [the] awaitable completes and returns the result data.

It uses the yield from implementation with an extra step of validating
its argument. await only accepts an awaitable, which can be one of:

* A native coroutine object returned from a native coroutine function.

* A generator-based coroutine object returned from a function
decorated with types.coroutine().

* An object with an __await__ method returning an iterator.

Any yield from chain of calls ends with a yield. This is a fundamental
mechanism of how Futures are implemented. Since, internally,
coroutines are a special kind of generators, every await is suspended
by a yield somewhere down the chain of await calls (please refer to
PEP 3156 for a detailed explanation).

To enable this behavior for coroutines, a new magic method called
__await__ is added. In asyncio, for instance, to enable Future objects
in await statements, the only change is to add __await__ = __iter__
line to asyncio.Future class.

[remainder of section snipped for brevity]
"""

Points to note: "similarly to yield from"; "uses the yield from
implementation"; "internally, coroutines are a special kind of
generators"; "every await is suspended by a yield"; "to enable Future
objects in await statements, the only change is to add __await__ =
__iter__".

"await" was designed to be a *drop-in replacement* for "yield from" so
your insistence that they're unrelated is kind of mind-boggling.
-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to