2009-10-16 16 views
6

Recentemente ho incappato in un'apparente incoerenza nel modo in cui Python trattava altre clausole in diverse dichiarazioni composte. Dato che Python è così ben progettato, sono sicuro che c'è una buona spiegazione, ma non riesco a pensarci.Perché diversamente si comportano in modo diverso nelle istruzioni for/while rispetto alle istruzioni if ​​/ try?

Si consideri il seguente:

if condition: 
    do_something() 
else: 
    do_something_else() 

Qui, do_something_else() viene eseguito solo se condition è falso, come previsto.

Analogamente, in

try: 
    do_something() 
except someException: 
    pass: 
else: 
    do_something_else() 
finally: 
    cleanup() 

do_something_else() viene eseguita solo se si è verificata un'eccezione.

In cicli for o while, viene sempre eseguita una clausola else, indipendentemente dal fatto che il contenuto di for/while block sia stato eseguito o meno.

for i in some_iterator: 
    print(i) 
else: 
    print("Iterator is empty!") 

sarà sempre print "Iterator è vuoto!", Se io dico some_iterator = [] o some_iterator = [1,2,3]. Stesso comportamento nelle clausole while-else. Mi sembra che else si comporti più come finally in questi casi. Cosa sto trascurando?

+0

Sono sorpreso che Python consenta la sintassi. Nella maggior parte degli altri linguaggi -else è limitato a essere utilizzato solo con if- o istruzioni switch. For-loops e try-statement potrebbero controllare il flusso, ma non sono condizionali come un'istruzione if, quindi -else non ha posto in essi. – shuckster

+2

Per quello che vale, c'è stata una lunga discussione lunga su/else, et al, sulla lista delle idee python, riassunta qui: http://article.gmane.org/gmane.comp.python.ideas/6131 /. Lo stesso Guido ammette di avere ripensamenti al riguardo: http://article.gmane.org/gmane.comp.python.ideas/6133/ –

+0

Grazie per questi link! –

risposta

5

Bene, dipende da come lo vedi. Potete guardare il elses come questo (scusa le urla, il suo l'unico modo per fare enfasi nel codice):

if condition: 
    do_something() 
IF THE PREVIOUS CONDITION WAS FALSE: 
    do_something_else() 

Ora, v'è una somiglianza evidente tra if/else e try/tranne/else, se vedi la dichiarazione else come un altro per l'istruzione except. Come questo.

try: 
    do_something() 
IF THERE WAS AN EXCEPTION: 
    pass: 
IF THE PREVIOUS CONDITION WAS FALSE: 
    do_something_else() 
finally: 
    cleanup() 

Lo stesso vale per l'altro/a:

IF some_iterator IS NOT EMPTY: 
    i = next(some_iterator) 
    print(i) 
IF THE PREVIOUS CONDITION WAS FALSE: 
    print("Iterator is empty!") 

Così qui vediamo che l'altro in qualche modo fondamentale fare lavoro esattamente lo stesso in tutti e tre i casi.

Ma si può anche vedere l'altro in questo modo:

try: 
    do_something() 
except someException: 
    pass: 
IF NO EXCEPTION: 
    do_something_else() 
finally: 
    cleanup() 

E allora non è più lo stesso, ma l'altro perché una sorta di "se non altro".Si può vedere di/altro nello stesso modo:

for i in some_iterator: 
    print(i) 
IF NO MORE ITERATING: 
    print("Iterator is empty!") 

Ma poi di nuovo, considerando l'Elif, allora questo modo di vedere funziona per if/else così:

if condition: 
    do_something() 
elif otherconditaion: 
    do_anotherthing() 
IF NO CONDITION WAS TRUE: 
    do_something_else() 

in che modo si voglio guardare il resto dipende da te, ma in entrambi i modi di vedere, altrimenti hanno somiglianze in tutti e tre i casi.

+0

Grazie. Questo ha senso e risponde alla mia domanda. –

13

Il for else costrutto esegue la clausola else se non break dichiarazione è stata eseguita per il ciclo, as described here Ad esempio, questa clausola else non viene mai valutata

for i in range(1,10): 
    if i % 5 == 0: 
     print i 
     break 
else: 
    print "nothing divisible by 5" 
+0

Esatto, quindi un'istruzione for/while-else ha senso solo se c'è un'istruzione break da qualche parte. –

4

Sì, come detto Eli, la clausola else viene solo eseguito se non si rompe. Essa vi impedisce di implementare il codice come questo:

for i in range(1,10): 
    if i % 5 == 0: 
     print i 
     break 
if i % 5 != 0: 
    print "nothing divisible by 5" 

che è grosso modo equivalente qui, ma a portata di mano se le condizioni per smettere sono un po 'più complicato (come il controllo varie condizioni possibili o combinazioni di condizioni).

Problemi correlati