python 协程与连续与发生器

pb3s4cty  于 2022-12-25  发布在  Python
关注(0)|答案(3)|浏览(128)

协程与延续和生成器之间的区别是什么?

iklwldmw

iklwldmw1#

我将从生成器开始,因为它们是最简单的情况。正如@zvolkov提到的,它们是可以被重复调用而不返回的函数/对象,但是当被调用时,它们将返回(产生)一个值,然后暂停它们的执行。当再次调用它们时,它们将从上次暂停执行的位置启动,并再次执行它们的操作。
生成器本质上是一个精简的(非对称的)协同程序,协同程序和生成器的区别在于协同程序可以在最初被调用后接受参数,而生成器不能。
要想出一个在哪里使用协程的小例子有点困难,但我已经做了最好的尝试,以这段(编造的)Python代码为例。

def my_coroutine_body(*args):
    while True:
        # Do some funky stuff
        *args = yield value_im_returning
        # Do some more funky stuff

my_coro = make_coroutine(my_coroutine_body)

x = 0
while True:
   # The coroutine does some funky stuff to x, and returns a new value.
   x = my_coro(x)
   print x

使用协程的一个例子是词法分析器和语法分析器。如果语言中没有协程,或者没有以某种方式模拟协程,词法分析和语法分析代码需要混合在一起,即使它们实际上是两个独立的关注点。但是使用协程,你可以将词法分析和语法分析代码分开。
(我将略谈对称协程和非对称协程之间的区别。只要说它们是等价的就够了,您可以从一个协程转换到另一个协程,而非对称协程--最像生成器--更容易理解。我概述了如何在Python中实现非对称协程。)
continuation实际上是非常简单的东西。它们只是表示程序中另一个点的函数,如果你调用它,就会导致执行自动切换到函数所表示的点。你每天都在使用它们的非常有限的版本,甚至没有意识到这一点。例外,例如,可以被认为是一种由内而外的延续,我将给予你一个基于Python的延续的伪代码示例。
假设Python有一个名为callcc()的函数,这个函数有两个参数,第一个是函数,第二个是调用它的参数列表,对这个函数的唯一限制是最后一个参数是函数(这将是我们当前的continuation)。

def foo(x, y, cc):
   cc(max(x, y))

biggest = callcc(foo, [23, 42])
print biggest

所发生的事情是callcc()将依次使用当前延续调用foo()cc),也就是对程序中调用callcc()的点的引用。当foo()调用当前continuation时,本质上与告诉callcc()返回调用当前continuation时使用的值相同。并且当它这样做时,它将堆栈回滚到创建当前continuation的位置,即,当您调用callcc()时。
所有这一切的结果将是我们假设的Python变体将打印'42'

mrzz3bfm

mrzz3bfm2#

协程是几个过程中的一个,这些过程轮流完成自己的工作,然后暂停以将控制权交给组中的其他协程。
Continuation是传递给某个过程的“函数指针”,在该过程完成时执行(“continued with”)。
Generator(在.NET中)是一种语言构造,它可以吐出一个值,“暂停”方法的执行,然后在请求下一个值时从同一点继续。

osh3o9ms

osh3o9ms3#

在较新版本的Python中,可以使用generator.send()向Generators发送值,这使得python Generators有效地协同执行。
python Generator与其他生成器(比如greenlet)的主要区别在于,在python中,yield value只能返回给调用者,而在greenlet中,target.switch(value)可以将你带到一个特定的目标协程,并产生一个值,在该值下target将继续运行。

相关问题