2017-10-19 100 views
1

a comment由吉姆·希利亚德Fasarakis:为什么基于生成器的协程消耗异步生成器异步数据生成器以及协程异步数据使用者?

发电机:包含一个或多个yield表达式def功能。

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

我能理解。

基于生成器的协程:由types.coroutine包裹的发电机(def + yield)。如果需要将它视为协程对象,则需要将其包装在 types.coroutine中。

发电的协同程序作为消费者(你.send值 他们或子发电机他们yield from)。

什么是“消费者(你.send值,他们或子发电机他们yield from)”是什么意思?

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

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

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

协程:async def无零个或多个await S和没有yield秒。

协同程序是异步数据消费者

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

谢谢。

回答

2

在蟒蛇,发电机在许多不同的方式,现在使用。 生成器的最初目的是暂停执行,然后yield返回一个值给调用者。然后调用者可以稍后调用以恢复发生器。因此发电机是数据生产者。

现在上述版本的生成器只允许通过yield语句返回数据。现在,函数是一个协程,它也应该接受来自调用者的值。因此PEP 342在蟒蛇推出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。您可以使用装饰器将现有的发电机类型转换为协同型。这些消费者可以通过send()接受价值,并使用yield from将其委托给子发电机。

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

没有简单yield的任何协程将成为数据使用者,因为它必须通过await调用另一个协程才能获得异步数据。