Python 协同程序vs延续vs生成器

Python 协同程序vs延续vs生成器,python,generator,coroutine,continuations,Python,Generator,Coroutine,Continuations,协同程序、延续程序和生成器之间的区别是什么?协同程序是轮流执行其工作,然后暂停以控制组中其他协同程序的几个过程之一 Continuation是传递给某个过程的“函数指针”,当该过程完成时将执行(“Continuation with”) Generator(在.NET中)是一种语言构造,它可以吐出一个值,“暂停”方法的执行,然后在请求下一个值时从同一点开始执行。我将从Generator开始,因为它们是最简单的情况。正如@zvolkov所提到的,它们是可以重复调用而不返回的函数/对象,但调用时将返回

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

协同程序是轮流执行其工作,然后暂停以控制组中其他协同程序的几个过程之一

Continuation是传递给某个过程的“函数指针”,当该过程完成时将执行(“Continuation with”)


Generator(在.NET中)是一种语言构造,它可以吐出一个值,“暂停”方法的执行,然后在请求下一个值时从同一点开始执行。

我将从Generator开始,因为它们是最简单的情况。正如@zvolkov所提到的,它们是可以重复调用而不返回的函数/对象,但调用时将返回(产生)一个值,然后暂停执行。当他们再次被调用时,他们将从上次暂停执行的位置启动,并再次执行他们的操作

生成器本质上是一个缩减(非对称)的协程。协同程序和生成器之间的区别在于,协同程序可以在初始调用后接受参数,而生成器不能

要想出一个使用协同程序的小例子有点困难,但这是我最好的尝试。以这个(编成的)Python代码为例

def my_coroutine_body(*args):
尽管如此:
#做些时髦的事
*args=收益率值
#做一些更时髦的事情
my_coro=制作协同程序(my_corroutine_body)
x=0
尽管如此:
#协同程序对x执行一些奇怪的操作,并返回一个新值。
x=我的科罗(x)
打印x
使用协同路由的一个例子是lexer和parser。如果没有语言中的协同程序或以某种方式进行模拟,则需要将词法分析和解析代码混合在一起,即使它们实际上是两个独立的关注点。但是使用协同程序,您可以分离出词法分析和解析代码

(我将讨论对称协同路由和非对称协同路由之间的区别。只要说它们是等效的,就可以从一个转换到另一个,而非对称协同路由(最像生成器)更容易理解。我概述了如何在Python中实现非对称协同路由。)

连续体实际上很简单。它们都是表示程序中另一点的函数,如果调用它,将导致执行自动切换到函数所表示的点。你每天都在不知不觉中使用非常有限的版本。例如,异常可以看作是一种由内而外的延续。我将为您提供一个基于Python的伪代码延续示例

假设Python有一个名为
callcc()
的函数,这个函数有两个参数,第一个是函数,第二个是调用它的参数列表。对该函数的唯一限制是,它接受的最后一个参数将是一个函数(这将是我们当前的继续)

def foo(x,y,cc):
cc(最大(x,y))
最大值=callcc(foo[23,42])
打印最大
将发生的情况是,
callcc()
将依次使用当前的延续(
cc
)调用
foo()
,即对程序中调用
callcc()
的点的引用。当
foo()
调用当前延续时,它本质上与告诉
callcc()
返回调用当前延续时使用的值相同,当它这样做时,它会将堆栈回滚到创建当前延续的位置,即调用
callcc()

所有这些的结果将是我们假设的Python变体将打印
'42'


我希望这能有所帮助,而且我相信我的解释可以改进很多

在较新版本的Python中,您可以使用
generator.send()
将值发送到生成器,这使Python生成器能够有效地协同工作


python生成器和其他生成器(比如greenlet)之间的主要区别在于,在python中,
yield值只能返回给调用方。在greenlet中,
target.switch(value)
可以将您带到特定的目标协同程序,并生成一个值,
target
将继续运行。

我意识到答案可能不准确,但在这一级别的问题上,我尝试保持简单。此外,我自己也不太明白:)python中的生成器类似于C#版本,但它是作为一种特殊语法实现的,用于创建迭代器对象的实例,该实例返回您提供的“函数”定义返回的值。一个小的更正:“…包括调用堆栈和所有变量,但不包括它们的值”(或直接删除“所有变量”)。Continuations不保留这些值,它们只包含调用堆栈。不,Continuations不是“指向函数的指针”“。在最简单的实现中,它包含一个指向函数的指针,并且环境保存局部变量。它永远不会返回,除非您使用call/cc之类的东西用返回值捕获它。我想知道协程和continuations是否有效地等效。我知道可以用continuations对协同进程进行建模,但是是否可以用continuations对协同进程进行建模,因为continuations严格来说更强大?一个缺点:带分隔符的continuations是函数,但不带分隔符的continuations不是:这是一个很好的观点。也就是说,在大多数实际应用中,当人们说“continuation”时,他们指的是部分/分隔的continuation。引入各种其他类型的连续体会使解释有些混乱。连续体不是函数,尽管它们可以具体化为函数。“这就是说,在大多数实际应用中,当人们说‘继续’时,他们是好的