2010-05-31 6 views
11

Así, en Python (aunque creo que se puede aplicar a muchos idiomas), me encuentro con algo como esto muy a menudo:pequeña redundancia de código dentro mientras que los bucles (no se siente limpio)

the_input = raw_input("what to print?\n") 
while the_input != "quit": 
    print the_input 
    the_input = raw_input("what to print?\n") 

Tal vez estoy siendo demasiado quisquilloso, pero no me gusta cómo debe repetirse la línea the_input = raw_input("what to print?\n"). Disminuye la facilidad de mantenimiento y la organización. Pero no veo ninguna solución alternativa para evitar el código duplicado sin empeorar aún más el problema. En algunos idiomas, podría escribir algo como esto:

while ((the_input=raw_input("what to print?\n")) != "quit") { 
    print the_input 
} 

Esto es definitivamente no Pythonic, y Python no permite ni siquiera para la asignación dentro de las condiciones de bucle que yo sepa.

Este código válido fija la redundancia,

while 1: 
    the_input = raw_input("what to print?\n") 
    if the_input == "quit": 
     break 
    print the_input 

pero no se siente del todo bien tampoco. El while 1 implica que este ciclo se ejecutará para siempre; Estoy usando un bucle, pero dándole una condición falsa y poniendo el real dentro de él.

¿Estoy siendo demasiado quisquilloso? ¿Hay una mejor manera de hacer esto? ¿Quizás hay alguna construcción de lenguaje diseñada para esto que yo no sepa?

+1

Creo que la primera forma es perfectamente aceptable. –

+5

Este es un patrón común llamado [loop y half] (http://www.cs.duke.edu/~ola/patterns/plopd/loops.html#loop-and-a-half). –

Respuesta

30

Piense iteradores - por ejemplo, en este caso específico:

for the_input in iter(lambda: raw_input('what to print?\n'), 'quit'): 
    print the_input 

La mayoría de los bucles en Python, excepto en los niveles más bajos de abstracciones, se implementan mejor como for lazos con la ayuda de algún subalterno iterador que captura la "lógica de bucle" - el iter incorporado puede ayudar (como aquí), a veces genexps (expresiones de generador) puede, a veces el módulo de biblioteca estándar itertools viene al rescate.

mayoría de las veces elegirán código personalizado funciones del generador (que utilizan yield), o más ocasiones (cuando se necesita la administración del estado muy sofisticada) una clase de iterador (una definición del método __iter__ especial como return self, y next [[o __next__ en las últimas versiones de Python]] para volver "al siguiente valor de la iteración).

la captura de la lógica de bucle, aparte de lo que sea que hace sobre los diferentes puntos producidos de forma secuencial el lazo itse ¡Si es la ayuda-abstracción clave aquí!

+4

Eso se siente demasiado inteligente ... –

+0

+1: Prefiere 'for'-loops para la iteración. En cualquier idioma que los proporcione. – Johnsyweb

+0

Esta es una solución increíble. SO no me deja aceptar una respuesta por otros 4 minutos ;-) – Ponkadoodle

Cuestiones relacionadas