来自a comment的Jim Fasarakis Hilliard:
生成器:
def
包含一个或多个yield
表达式的函数。生成器用作数据生成器(它们是
yield
个值)。
我能理解。
基于生成器的协同程序:由
types.coroutine
包装的生成器(def
+yield
)。你需要把它包起来types.coroutine
如果您需要将其视为协程对象。基于生成器的协同程序用作使用者(您
.send
的值为yield from
他们或他们.send
)的子发电机。
“消费者(您yield from
对他们或他们async def
)的子发电机的价值是什么意思?”
异步生成器:包含一个或多个
yield
表达式的await
函数。这些也可以包含async def
个表达式。异步生成器是异步数据生成器。
“异步数据生成器”是什么意思?
协程:
await
没有零个或多个yield
s且没有<property> <name> yarn.nodemanager.disk-health-checker.max-disk-utilization-per-disk-percentage </name> <value>90.0</value> <source>yarn-default.xml</source> </property>
个。协同程序是异步数据使用者。
“异步数据使用者”是什么意思?
感谢。
答案 0 :(得分:3)
在python中,现在可以通过多种方式使用生成器。 生成器的最初目的是暂停执行,然后yield
将值返回给调用者。然后呼叫者可以稍后呼叫以恢复发电机。因此,发电机是数据生产者。
现在,上述版本的生成器只允许通过yield
语句返回数据。现在,为了使一个函数成为一个协程,它也应该接受来自调用者的值。因此,PEP 342在python 2.5中引入了增强生成器,以便它们可以充当完全成熟的协程。这允许调用者将值发送给生成器。
现在新问题是,当生成器被重构并且您想要将其操作的一部分委托给子生成器时,您需要显式调用子生成器作为迭代器,传播调用者发送的数据并处理异常。为了简化子生成器的操作,在PEP 380中定义了一个新的操作 yield from
作为python 3.3的一部分。 yield from
在语法上远远超过普通的yield语法。在完美的世界中,可能会使用新的关键字。
现在的问题是发电机在两种不同的环境中使用。作为迭代器和协程。如果可以将生成器明确定义为协程,那会更好。因此,Python 3.5中的PEP 492 introduced async
and 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
调用另一个协程来获取异步数据。