Actualización: Lo que realmente quería desde el principio era greenlets.¿Programación estructurada y generadores Python?
Nota: Esta pregunta mutado un poco como la gente respondió y me obligó a "subir la apuesta", como mis ejemplos triviales tenían simplificaciones triviales; en lugar de continuar mutando aquí, dejaré la pregunta cuando la tenga más clara en mi cabeza, según la sugerencia de Alex.
generadores de Python son una cosa de belleza, pero ¿cómo puedo romper fácilmente uno en módulos (programación estructurada)? Yo efectivamente quiero PEP 380, o al menos algo comparable en la carga de la sintaxis, pero en Python existente (por ejemplo 2.6)
Como un ejemplo (la verdad es estúpida), tome las siguientes:
def sillyGenerator():
for i in xrange(10):
yield i*i
for i in xrange(12):
yield i*i
for i in xrange(8):
yield i*i
Siendo un ferviente creyente en SECO, diviso el patrón que se repite aquí y el factor hacia fuera en un método:
def quadraticRange(n):
for i in xrange(n)
yield i*i
def sillyGenerator():
quadraticRange(10)
quadraticRange(12)
quadraticRange(8)
... que por supuesto no funciona. El padre debe llamar a la nueva función en un bucle, produciendo los resultados:
def sillyGenerator():
for i in quadraticRange(10):
yield i
for i in quadraticRange(12):
yield i
for i in quadraticRange(8):
yield i
... que es incluso más largo que antes!
Si deseo insertar parte de un generador en una función, siempre necesito este envoltorio bastante detallado y de dos líneas para llamarlo. Se pone peor si deseo admitir el envío():
def sillyGeneratorRevisited():
g = subgenerator()
v = None
try:
while True:
v = yield g.send(v)
catch StopIteration:
pass
if v < 4:
# ...
else:
# ...
Y eso no está teniendo en cuenta la aprobación de excepciones. ¡El mismo texto repetitivo todo el tiempo! Sin embargo, uno no puede aplicar DRY y factorizar este código idéntico en una función, porque ... ¡necesitaría el texto repetitivo para llamarlo! Lo que quiero es algo como:
def sillyGenerator():
yield from quadraticRange(10)
yield from quadraticRange(12)
yield from quadraticRange(8)
def sillyGeneratorRevisited():
v = yield from subgenerator()
if v < 4:
# ...
else:
# ...
¿Alguien tiene una solución a este problema? Tengo un intento de primer intento, pero me gustaría saber qué han hecho otros. En última instancia, cualquier solución tendrá que abordar ejemplos en los que el generador principal realiza una lógica compleja basada en el resultado de los datos enviados al generador, y potencialmente hace una gran cantidad de llamadas a los subgeneradores: mi caso de uso son los generadores utilizados para implementar máquinas de estado complejas de larga ejecución.
¿Podría simplificar su problema real (no demasiado, solo lo suficiente) en lugar de inventar uno que no parece coincidir muy bien? –
Ejemplo: no realmente. Solo quiero una respuesta sobre cómo puedo descomponer un generador complejo sin un ámbito de repetición, similar a la declaración de "rendimiento de" que se describe a continuación, pero en Python existente. Los trucos que satisfacen casos simples no son suficientes :( –