【问题标题】:How do coroutines in Python compare to those in Lua?Python 中的协程与 Lua 中的协程相比如何?
【发布时间】:2024-04-22 18:35:01
【问题描述】:

functions in the coroutine table,主要是 createresumeyield 提供了对 Lua 中协程的支持。开发人员将这些协程描述为stackful, first-class and asymmetric

协程也可以在 Python 中使用,可以使用 enhanced generators(和 yield from),或者在 3.5 版中添加,async and await

Python 中的协程与 Lua 中的协程相比如何?它们也是堆叠的、一流的和不对称的吗?

为什么 Python 需要这么多的构造(async defasync withasync forasynchronous comprehensions、...)来构建协程,而 Lua 只能为它们提供三个内置函数?

【问题讨论】:

  • 个人猜测为什么 python 需要这么多结构:它是最近才被引入语言的,需要适应现有语法的工作(在其他语句中添加async)你似乎链接到大量解释各种构造如何工作的资源 - 文档没有回答您的问题吗?
  • 我不知道 python 协程是如何工作的,但是如果你需要 Lua 协程方面的帮助,我可以 :)
  • Here's 一篇关于 python asyncio 的好帖子,如果有点啰嗦...对于 Lua,我一直认为 Documentation 写得很好

标签: python asynchronous lua async-await coroutine


【解决方案1】:

简单的答案是它们是不同的语言。是的,Python 协程是可堆叠的、一流的和非对称的。看到这个答案:Coroutine vs Continuation vs Generator

来自 Lua documentation:

有些人称非对称协程为半协程(因为他们 不是对称的,它们不是真正的 co)。然而,其他人 使用同一个术语 semi-coroutine 来表示受限的实现 协程,其中协程只能在以下情况下暂停其执行 它不在任何辅助函数内部,也就是说,当它没有 在其控制堆栈中挂起的调用。也就是说,只有主体 这样的半协程可以产生。 Python中的生成器就是一个例子 半协程的这个含义。

与对称协程和非对称协程之间的区别不同, 协程和生成器之间的区别(如 Python 中所示) 是深的;生成器根本不够强大,无法实现 几个有趣的结构,我们可以用 true 来写 协程。 Lua 提供了真正的非对称协程。喜欢的人 对称协程可以在非对称协程之上实现它们 Lua的设施。这是一项简单的任务。 (基本上,每次传输都会 一个收益,然后是一份简历。)

另外,请参阅 Python 开发者邮件列表上的讨论:PEP 492: What is the real goal?

【讨论】:

    【解决方案2】:

    我刚刚第一次看到lua,其中包括sieve.lua live demo。它是使用协程的 Erathostenes 筛子的实现。我的直接想法是:这在 python 中看起来会更干净:

    #!/usr/bin/env python3
    
    # sieve.py
    # the sieve of Eratosthenes programmed with a generator functions
    # typical usage: ./sieve.py 500 | column
    
    import sys
    
    # generate all the numbers from 2 to n
    def gen(n):
        for i in range(2,n):
            yield i
    
    # filter the numbers generated by `g', removing multiples of `p'
    def filter(p, g):
        for n in g:
            if n%p !=0:
                yield n
    
    N=int(sys.argv[1]) if len(sys.argv)>1 else 500 # from command line
    x=gen(N)                     # generate primes up to N
    while True:
        try:
            n = next(x)          # pick a number until done
        except StopIteration:
            break
        print(n)                 # must be a prime number
        x = filter(n, x)         # now remove its multiples
    

    这与问题没有太大关系,但在我使用Python 3.4.3 的机器上,N>7500 在某处发生堆栈溢出。将sieve.luaLua 5.2.3 一起使用,堆栈溢出已经发生在N>530

    生成器对象(代表暂停的协程)可以像任何其他对象一样被传递,并且内置的 next() 可以在任何地方应用于它,因此 python 中的协程是一流的。如果我错了,请纠正我。

    【讨论】:

    • 是的,我知道没有必要定义函数gen(x),因为x=gen(N) 可以被x=iter(range(2,N)) 替换。我想靠近sieve.lua
    • 堆栈溢出可以通过在llimits.h中增加LUAI_MAXCCALLS来轻松修复。
    最近更新 更多