python - 协程、延续、生成器

标签 python generator coroutine continuations

协程、延续和生成器之间有什么区别?

最佳答案

我将从生成器开始,因为它们是最简单的情况。正如 @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()的函数,这个函数有两个参数,第一个是一个函数,第二个是调用它的参数列表。该函数的唯一限制是它采用的最后一个参数将是一个函数(这将是我们当前的延续)。

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

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

会发生的情况是,callcc() 会依次使用当前延续 (cc) 调用 foo(),即对程序中调用 callcc() 的点的引用。当 foo() 调用当前延续时,它本质上与告诉 callcc() 返回调用当前延续的值相同,以及何时返回也就是说,它会将堆栈回滚到创建当前延续的位置,即当您调用 callcc() 时。

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

关于python - 协程、延续、生成器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/715758/

相关文章:

c# - 使用协程循环

android - 在 kotlin 协程中实现 async-await()

wsgi - 使用 Gevent 和 WSGI 阻止调用

python - 如何使用 pandas 在 Excel 工作表中的同一个图形上绘制多个数据框?

python - 导入 PyQt5.QtWidgets 模块的最佳实践

Python如何对二维数据的大点云进行插值

python - start_request 方法中的 Scrapy yield 响应对象

c++ - 将迭代器实现为具有引用语义的抽象生成器的正确方法

Python 产量生成器函数

python - 在这个硬币找零问题中,我该如何做 "recursive"for 循环?