摘自Jim Fasarakis Hilliard的评论:
生成器:
def
包含一个或多个yield
表达式的函数。生成器用作数据生产者(它们
yield
值)。
我能理解。
基于生成器的协程:由
types.coroutine
包装的生成器 (def
+yield
)。你需要把它包裹起来types.coroutine
是否需要将其视为协程对象。基于生成器的协程用作使用者(
.send
值 他们或他们yield from
的子生成器)。
"消费者(你.send
他们或他们yield from
的子生成器的价值)"是什么意思?
异步生成器:
async def
包含一个或多个yield
表达式的函数。这些还可以包含await
表达式。异步生成器是异步数据生成器。
"异步数据生成者"是什么意思?
协程:没有零个或多个
await
s 且没有yield
s 的async def
。协程是异步数据使用者。
"异步数据使用者"是什么意思?
谢谢。
在python中,生成器现在以多种不同的方式使用。生成器的最初目的是暂停执行,然后将值yield
回调用方。然后,调用方可以稍后调用 next 以恢复生成器。因此,生成器是数据生产者。
现在上述版本的生成器只允许通过yield
语句返回数据。现在,要使函数成为协程,它还应该接受来自调用方的值。因此,PEP 342在 python 2.5 中引入,以增强生成器,以便它们可以充当完整的协程。这允许调用方将值发送到生成器。
现在的新问题是,当生成器被重构并且您希望将其部分操作委托给子生成器时,您需要显式调用子生成器作为迭代器,传播调用方发送的数据并处理异常。为了简化子生成器的操作,PEP 380 中定义了一个新的操作yield from
作为 python 3.3 的一部分。yield from
在语法上比普通的屈服语法要多得多。在一个完美的世界里,可能会使用一个新的关键字。
现在的问题是发电机是在两种不同的环境中使用的。作为迭代器和协程。如果可以将生成器显式定义为协程,那就更好了。因此,PEP 492在 Python 3.5 中引入了async
和await
关键字。因此,任何用作协程的生成器都由async
关键字指示。Python 3.5 中的协程可以使用await
关键字代替yield from
。请注意,从 python 3.5 开始,协程是一种不同的类型!!
现在假设您有一个具有def
和yield
的生成器函数。可以使用types.coroutine
修饰器将现有生成器类型转换为协程类型。这些是可以通过send()
接受值并使用yield from
将其委托给子生成器的消费者。
在 python 3.5 中,您可以使用async
来指示函数是协程类型。这样的函数可以包含普通yield
和await
。它们不能包含yield from
(因为await
替换要素)。当一个协程包含普通yield
时,它们是生成器调用链中最低的,因此称为异步数据生产者。
任何没有纯yield
的协程都将是数据使用者,因为它必须通过await
调用另一个协程才能获取异步数据。