2010-05-31 8 views
11

Così, in Python (anche se penso che può essere applicato a molte lingue), mi ritrovo con qualcosa di simile abbastanza spesso:piccolo ridondanza di codice all'interno di while-loop (non si sente pulito)

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

Forse sono troppo pignolo, ma non mi piace come la linea the_input = raw_input("what to print?\n") debba essere ripetuta. Riduce la manutenibilità e l'organizzazione. Ma non vedo alcuna soluzione alternativa per evitare il codice duplicato senza peggiorare ulteriormente il problema. In alcune lingue, potrei scrivere qualcosa di simile:

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

Questo è sicuramente non Pythonic, e Python non ha nemmeno permetto di assegnazione all'interno di condizioni di loop AFAIK.

Questo codice valido fissa la ridondanza,

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

Ma non si sente abbastanza di destra entrambi. Il while 1 implica che questo ciclo verrà eseguito per sempre; Sto usando un loop, ma dandogli una condizione falsa e inserendone quella reale al suo interno.

Sono troppo schizzinoso? C'è un modo migliore per farlo? Forse c'è un costrutto linguistico progettato per questo che non conosco?

+1

Penso che la prima forma sia perfettamente accettabile. –

+5

Questo è un modello comune chiamato [loop e mezzo] (http://www.cs.duke.edu/~ola/patterns/plopd/loops.html#loop-and-a-half). –

risposta

30

Pensate iteratori - ad esempio, nel caso specifico:

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

La maggior parte dei loop in Python, se non a livelli molto più bassi di astrazioni, sono meglio implementati come for loop, con l'aiuto di qualche subalterno iteratore che cattura la "logica di loop" - il iter integrato può aiutare (come in questo caso), a volte i genexps (espressioni di generatore) possono, a volte il modulo di libreria standard itertools viene in soccorso.

maggior parte dei casi si sceglie di codice personalizzato funzioni del generatore (quelli che utilizzano yield), o più di tanto in tanto (quando si ha bisogno davvero sofisticata gestione dello stato) un costume classe iteratore (uno che definisce il metodo __iter__ speciale come return self, e next [[o __next__ nelle ultime versioni di Python]] per tornare "il valore successivo dalla ripetizione).

Catturare la logica loop a parte qualunque cosa è che si fare sulle varie voci in sequenza prodotti da il ciclo itse Se è l'astrattore-chiave qui!

+4

Sembra un po 'troppo intelligente ... –

+0

+1: preferisci "per" i cicli per l'iterazione. In qualsiasi lingua che li fornisce. – Johnsyweb

+0

Questa è una soluzione incredibile. SO non mi permette di accettare una risposta per altri 4 minuti però ;-) – Ponkadoodle