¿Cómo se comparan las coroutinas en Python con las de Lua?
asynchronous async-await (2)
El soporte para coroutines en Lua es proporcionado por funciones en la tabla de coroutine
, principalmente create
, resume
y yield
. Los desarrolladores describen estas coroutinas como apiladas, de primera clase y asimétricas .
Coroutines también está disponible en Python, ya sea utilizando generadores mejorados (y yield from
) o, agregados en la versión 3.5, async
y en await
.
¿Cómo se comparan las coroutinas en Python con las de Lua? ¿Son también apilables, de primera clase y asimétricas?
¿Por qué Python requiere tantas construcciones ( async def
, async with
, async for
, asynchronous comprensions , ...) para coroutines, mientras que Lua puede proporcionarles solo tres funciones integradas?
Acabo de echar un vistazo a lua
, que incluía la sieve.lua
vivo de sieve.lua
. Es una implementación del tamiz de Erathostenes utilizando coroutines. Mi pensamiento inmediato fue: Esto se vería mucho más limpio en 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
Esto no tiene mucho que ver con la pregunta, pero en mi máquina usando Python 3.4.3
produce un desbordamiento de pila en algún lugar para N>7500
. Al usar sieve.lua
con Lua 5.2.3
el desbordamiento de pila ya ocurre en N>530
.
Los objetos generadores (que representan una coroutine suspendida) se pueden pasar como cualquier otro objeto, y el next () incorporado se puede aplicar a él en cualquier lugar, por lo que las coroutines en python son de primera clase. Por favor, corríjame si estoy equivocado.
La respuesta simple es que son idiomas diferentes. Sí, Python coroutines son apilables, de primera clase y asimétricas. Ver esta respuesta: Coroutine vs Continuation vs Generator
De la Documentation Lua:
Algunas personas llaman semicoroutinas coroutinas asimétricas (porque no son simétricas, en realidad no lo son). Sin embargo, otras personas usan el mismo término semi-coroutine para denotar una implementación restringida de coroutines, donde un coroutine solo puede suspender su ejecución cuando no está dentro de ninguna función auxiliar, es decir, cuando no tiene llamadas pendientes en su pila de control. En otras palabras, solo el cuerpo principal de tales semi-coroutines puede ceder. Un generador en Python es un ejemplo de este significado de semi-coroutines.
A diferencia de la diferencia entre las coroutinas simétricas y asimétricas, la diferencia entre las coroutinas y los generadores (como se presenta en Python) es profunda; Los generadores simplemente no son lo suficientemente poderosos como para implementar varias construcciones interesantes que podemos escribir con coroutines verdaderos. Lua ofrece corutines verdaderos, asimétricos. Aquellos que prefieren las coroutinas simétricas pueden implementarlas sobre las instalaciones asimétricas de Lua. Es una tarea fácil. (Básicamente, cada transferencia hace un rendimiento seguido de un resumen).
También, vea esta discusión en la lista de correo de desarrolladores de Python: PEP 492: ¿Cuál es el objetivo real?