The purpose of PEP 525 -- Asynchronous Generators is pretty much similar to PEP 255 -- Simple Generators which introduced generators. It is mainly intented to make things easier to implement, only in a different domain (asynchronous one). From PEP 525:
Essentially, the goals and rationale for PEP 255, applied to the asynchronous execution case, hold true for this proposal as well.
In short, it makes writing objects that support the asynchronous iteration protocol easy. As generators did for the iterator protocol.
Instead of having to define objects that implement __aiter__
and __anext__
you create an asynchronous generator that does this seemingly by magic. This mirrors what generators did for the iterator protocol; instead of implementing __iter__
and __next__
for an object, you can just create a generator.
This is nicely stated in the rational of PEP 525 which also includes a nice example that shows the savings you make in code written when you use async generators.
In addition to code length savings, async generators also perform much better:
Performance is an additional point for this proposal: in our testing of the reference implementation, asynchronous generators are 2x faster than an equivalent implemented as an asynchronous iterator.
Just to add some terminology here because it's getting difficult to keep track of terms sometimes:
- Generators:
def
functions that contain one or more yield
expressions.
- Generator-based coroutine: A generator (
def
+ yield
) that is wrapped by types.coroutine
. You need to wrap it in types.coroutine
if you need it to be considered a coroutine object.
- Asynchronous Generator:
async def
functions that contain a one or more yield
expressions. These can also contain await
expressions.
- Coroutine:
async def
without zero or more await
s and no yield
s.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…