Как сопоставлять сопрограммы в Python по сравнению с Lua?

Поддержка сопрограмм в Lua обеспечивается функциями в таблице coroutine, в основном create, resume и yield, Разработчики описывают эти сопрограммы как stackful, первоклассный и асимметричный.

Coroutines также доступны в Python, используя расширенные генераторыyield from) или, добавлено в версии 3.5, async и await.

Как сопоставлять сопрограммы в Python по сравнению с Lua? Являются ли они стекловидными, первоклассными и асимметричными?

Почему Python требует так много конструкций (async def, async with, async for, асинхронных понятий,...) для сопрограммы, в то время как Lua может предоставить им только три встроенные функции?

Ответы

Ответ 1

Простым ответом является то, что они разные языки. Да, сопрограммы Python сложны, первоклассны и асимметричны. См. Этот ответ: Coroutine vs Continuation vs Generator

Из документа Lua :

Некоторые люди называют асимметричные полукоротки coroutine (потому что они не являются симметричными, они на самом деле не являются со). Однако другие люди использовать тот же термин sem-coroutine, чтобы обозначить ограниченную реализацию сопрограммы, где сопрограмма может только приостановить выполнение, когда он не находится внутри какой-либо вспомогательной функции, т.е. когда он не имеет ожидающих вызовов в стеке управления. Другими словами, только основной корпус таких полукорутингов. Например, генератор в Python этого значения полукоротов.

В отличие от разницы между симметричными и асимметричными сопрограммами, разница между сопрограммами и генераторами (как представлено на Python) является глубоким; генераторы просто недостаточно эффективны для реализации несколько интересных конструкций, которые мы можем написать с помощью истинных сопрограммы. Lua предлагает истинные асимметричные сопрограммы. Те, кто предпочитает симметричные сопрограммы могут реализовать их поверх асимметричных объектов Луа. Это непростая задача. (В принципе, каждая передача выход, за которым следует резюме.)

Также см. это обсуждение в списке почтовых ящиков разработчиков Python: PEP 492: Какова реальная цель?

Ответ 2

У меня только первый взгляд на lua, который включал sieve.lua живую демонстрацию. Это реализация решета эратостенов с помощью сопрограмм. Я сразу подумал: это выглядело бы намного чище в 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.lua с Lua 5.2.3, переполнение стека происходит уже при N>530.

Объекты генератора (которые представляют приостановленную сопрограмму) могут быть переданы как любой другой объект, а следующий() встроенный может быть применен к нему в любом месте, поэтому сопрограммы в python являются первоклассными. Пожалуйста, поправьте меня, если я ошибаюсь.