【问题标题】:Why are generator-based coroutines consumes, asynchronous generators asynchronous data producers, and coroutines asynchronous data consumers?为什么基于生成器的协程消费,异步生成器异步数据生产者,协程异步数据消费者?
【发布时间】:2018-03-31 00:42:45
【问题描述】:

来自 Jim Fasarakis Hilliard 的 a comment

生成器:def 包含一个或多个 yield 表达式的函数。

生成器用作数据生产者(它们yield 值)。

我能理解。

基于生成器的协程:由types.coroutine 包装的生成器 (def + yield)。你需要把它包起来 types.coroutine 如果您需要将其视为协程对象。

基于生成器的协程被用作消费者(你 .send 值 他们或他们yield from的子生成器。

“消费者(您.send 重视他们或他们yield from 的子生成器)”是什么意思?

异步生成器:async def 函数包含一个或多个 yield 表达式。这些也可以包含await 表达式。

异步生成器是异步数据生产者。

“异步数据生产者”是什么意思?

协程:async def 没有零个或多个 awaits,也没有 yields。

协程是异步数据消费者

“异步数据消费者”是什么意思?

谢谢。

【问题讨论】:

    标签: python python-3.x asynchronous generator coroutine


    【解决方案1】:

    在 python 中,生成器现在以多种方式使用。 生成器的最初目的是暂停执行,然后将 yield 一个值返回给调用者。然后调用者可以稍后调用 next 来恢复生成器。因此生成器是数据生产者。

    现在以上版本的生成器只允许通过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 开始,协程是不同的类型!!

    现在假设您有一个带有defyield 的生成器函数。您可以使用 types.coroutine 装饰器将现有的生成器类型转换为协程类型。这些消费者可以通过send() 接受值并使用yield from 将其委托给子生成器。

    在python 3.5中,可以使用async来表示该函数是协程类型。这样的函数可以包含普通的yieldawait。它们不能包含yield from(因为await 替换了该功能)。当协程包含普通的yield 时,它们是生成器调用链中最低的,因此称为异步数据生产者。

    任何没有纯yield 的协程都将成为数据消费者,因为它必须通过await 调用另一个协程来获取异步数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-09
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 2021-04-30
      • 2012-12-15
      • 1970-01-01
      • 2019-07-09
      相关资源
      最近更新 更多