Python equivalente de continuaciones con Ruby
-
10-07-2019 - |
Pregunta
¿Cuál es el equivalente en Python del siguiente código en Ruby?
def loop
cont=nil
for i in 1..4
puts i
callcc {|continuation| cont=continuation} if i==2
end
return cont
end
> c=loop
1
2
3
4
> c.call
3
4
Referencia: Secretos del éxito de desarrollo ligero, Parte 9: Continuaciones basados ??en marcos
Solución
El artículo que citó contiene un enlace a Continuaciones simplificadas e ilustradas en la sección Recursos, que habla sobre las continuaciones en el lenguaje Python.
Otros consejos
eche un vistazo al rendimiento declaración para hacer generadores.
No hablo rubí, pero parece que estás buscando esto:
def loop():
for i in xrange(1,5):
print i
if i == 2:
yield
for i in loop():
print "pass"
Editar: Me doy cuenta de que esto es básicamente una especialización de continuaciones reales, pero debería ser suficiente para la mayoría de los propósitos. Use yield
para devolver la continuación y el mensaje .next ()
en el generador (devuelto simplemente llamando a loop ()
) para volver a ingresar.
Uso de generator_tools
(para instalar: ' $ easy_install generator_tools
'):
from generator_tools import copy_generator
def _callg(generator, generator_copy=None):
for _ in generator: # run to the end
pass
if generator_copy is not None:
return lambda: _callg(copy_generator(generator_copy))
def loop(c):
c.next() # advance to yield's expression
return _callg(c, copy_generator(c))
if __name__ == '__main__':
def loop_gen():
i = 1
while i <= 4:
print i
if i == 2:
yield
i += 1
c = loop(loop_gen())
print("c:", c)
for _ in range(2):
print("c():", c())
Salida:
1
2
3
4
('c:', <function <lambda> at 0x00A9AC70>)
3
4
('c():', None)
3
4
('c():', None)
Hay muchas soluciones débiles que funcionan en casos especiales (ver otras respuestas a esta pregunta), pero no hay una construcción de lenguaje Python que sea equivalente a callcc
o que pueda usarse para construir algo equivalente a callcc
.
Es posible que desee probar Stackless Python o el greenlet Extensión de Python, las cuales proporcionan corutinas, en base a las cuales es posible construir continuas de una sola vez, pero eso es aún más débil que el
def loop():
def f(i, cont=[None]):
for i in range(i, 5):
print i
if i == 2:
cont[0] = lambda i=i+1: f(i)
return cont[0]
return f(1)
if __name__ == '__main__':
c = loop()
c()