Clausola Else su istruzione Python while


321

Ho notato che il seguente codice è legale in Python. La mia domanda è: perché? C'è un motivo specifico?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."

5
@detly: Questo perché la maggior parte delle persone evita questo costrutto. :) Credo che Guido abbia menzionato durante il processo Py3k che, per lo meno, la scelta della parola elseper questo uso era stata un'idea notevolmente negativa e che non avrebbero fatto più nulla di tutto ciò.
Nicholas Knight,

5
@Nicholas Knight - sì, per quanto allettante, probabilmente sarebbe qualcosa che solo io ho capito a prima vista. Qualsiasi altra povera linfa dovrebbe andare a guardare le specifiche della lingua, o tornare indietro nel tempo e pubblicare una domanda qui su Sta-heeeeey ...
detly

8
L'idea alla base della scelta di "altro" è che questo costrutto è presumibilmente spesso usato insieme a un "if X: break" all'interno del ciclo while. Dal momento che la clausola 'else' viene eseguita se non usciamo dal ciclo, forma una sorta di 'else' al 'if'.
Jonathan Hartley,

12
Dovrebbero rinominarlo after:.
naught101

Risposte:


388

La elseclausola viene eseguita solo quando la tua whilecondizione diventa falsa. Se sei breakfuori dal ciclo o se viene sollevata un'eccezione, non verrà eseguita.

Un modo di pensarci è come un costrutto if / else rispetto alla condizione:

if condition:
    handle_true()
else:
    handle_false()

è analogo al costrutto loop:

while condition:
    handle_true()
else:
    # condition is false now, handle and go on with the rest of the program
    handle_false()

Un esempio potrebbe essere il seguente:

while value < threshold:
    if not process_acceptable_value(value):
        # something went wrong, exit the loop; don't pass go, don't collect 200
        break
    value = update(value)
else:
    # value >= threshold; pass go, collect 200
    handle_threshold_reached()

42
"La clausola else viene eseguita solo quando la condizione while diventa falsa." La formulazione qui implica che il tuo stato while passa da uno stato di vero a falso e che l'altro verrà eseguito. Tuttavia, se il tempo non è mai vero, la clausola else verrà comunque eseguita.
user597608

pseudocodice Quindi correggimi se sbaglio, ma questo è esattamente lo stesso di while {} something tranne che somethingverrà saltato se sei breaknel whileciclo.
Daniel Kaplan,

2
Forse lo pseudocodice più preciso sarebbe: while (True) {if (cond) {handle_true (); } else {handle_false (); rompere; }}
VinGarcia,

2
"non passare, non collezionarne 200", ahah, tutti quelli che sanno da dove proviene hanno avuto una buona infanzia
Stefan Octavian,

102

La elseclausola viene eseguita se si esce normalmente da un blocco, colpendo la condizione del loop o cadendo dalla parte inferiore di un blocco try. Si Non eseguita se breako returnda un blocco, o di sollevare un'eccezione. Funziona non solo per while e per i loop, ma prova anche i blocchi.

In genere lo trovi in ​​luoghi in cui normalmente usciresti da un ciclo in anticipo e scappare alla fine del ciclo è un'occasione inaspettata / insolita. Ad esempio, se si esegue il ciclo in un elenco alla ricerca di un valore:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("

1
In realtà un costrutto abbastanza utile per una cosa del genere. Non so quante volte ho messo found_it=Falseall'inizio di un ciclo, quindi esegui un controllo se found_italla fine
Cruncher

42

In risposta a Is there a specific reason?, ecco un'applicazione interessante: uscire da più livelli di looping.

Ecco come funziona: il ciclo esterno ha una rottura alla fine, quindi sarebbe eseguito solo una volta. Tuttavia, se il ciclo interno viene completato (non trova alcun divisore), raggiunge l'istruzione else e l'interruzione esterna non viene mai raggiunta. In questo modo, un'interruzione nell'anello interno si romperà da entrambi gli anelli, anziché solo uno.

for k in [2, 3, 5, 7, 11, 13, 17, 25]:
    for m in range(2, 10):
        if k == m:
            continue
        print 'trying %s %% %s' % (k, m)
        if k % m == 0:
            print 'found a divisor: %d %% %d; breaking out of loop' % (k, m)
            break
    else:
        continue
    print 'breaking another level of loop'
    break
else:
    print 'no divisor could be found!'

Per entrambi whilee per i forloop, l' elseistruzione viene eseguita alla fine, a meno che non sia breakstata utilizzata.

Nella maggior parte dei casi ci sono modi migliori per farlo (inserendolo in una funzione o sollevando un'eccezione), ma funziona!


1
Non ho votato a fondo ma penso di sapere perché qualcuno lo ha fatto. Non stai rispondendo alla domanda e stai fornendo 14 righe di codice con solo 2 righe di descrizione. Se c'è una rilevanza per la domanda che non ci stai dicendo ...
BlueEel,

1
@BlueEel grazie per il feedback! Ho aggiunto ulteriori spiegazioni sul codice e ho chiarito in che modo risponde alla domanda (perché risponde a una parte di esso).
Segna il

Sei riuscito a mettere il tuo codice nel contesto e anche se non stai rispondendo a tutte le domande, ora vedo la rilevanza. Ho votato a favore della tua risposta in quanto ora è utile ai nuovi arrivati ​​e ai principianti (come me stesso per quanto riguarda il pitone). - Grazie, ho imparato qualcosa.
BlueEel,

Mi piace la semplice applicazione - ora vedo perché qualcuno potrebbe usarla. Anche se non ne ho mai visto il bisogno.
Gabe,

L'esempio mostra l'uso di for / else ma la domanda riguardava specificamente while / else.
Ian Goldby,

20

La clausola else viene eseguita quando la condizione while restituisce false.

Dalla documentazione :

L'istruzione while viene utilizzata per l'esecuzione ripetuta finché un'espressione è vera:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

Ciò verifica ripetutamente l'espressione e, se è vera, esegue la prima suite; se l'espressione è falsa (che potrebbe essere la prima volta che viene testata) la suite della elseclausola, se presente, viene eseguita e il ciclo termina.

breakUn'istruzione eseguita nella prima suite termina il ciclo senza eseguire la elseSuite di clausola. continueUn'istruzione eseguita nella prima suite salta il resto della suite e torna a testare l'espressione.


15

La mia risposta si concentrerà su QUANDO possiamo usare while / for-else.

A prima vista, sembra che non ci siano differenze nell'uso

while CONDITION:
    EXPRESSIONS
print 'ELSE'
print 'The next statement'

e

while CONDITION:
    EXPRESSIONS
else:
    print 'ELSE'
print 'The next statement'

Perché l' print 'ELSE'istruzione sembra sempre eseguita in entrambi i casi (sia quando il whileciclo è terminato o meno).

Quindi, è diverso solo quando l'istruzione print 'ELSE'non verrà eseguita. È quando c'è un breakdentro il blocco di codice sottowhile

In [17]: i = 0

In [18]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
else:
    print 'ELSE'
print 'The next statement'
   ....:
0
1
2
The next statement

Se diverso da:

In [19]: i = 0

In [20]: while i < 5:
    print i
    if i == 2:
        break
    i = i +1
print 'ELSE'
print 'The next statement'
   ....:
0
1
2
ELSE
The next statement

return non rientra in questa categoria, perché ha lo stesso effetto per due casi precedenti.

Inoltre, il rilancio dell'eccezione non causa differenze, poiché quando si alza, dove verrà eseguito il codice successivo è il gestore delle eccezioni (tranne il blocco), il codice nella elseclausola o subito dopo la whileclausola non verrà eseguito.


4

So che questa è una vecchia domanda ma ...

Come ha detto Raymond Hettinger, dovrebbe essere chiamato while/no_breakinvece di while/else.
Trovo facile capire e guardare questo frammento.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
if n == 0:
    print n

Ora invece di controllare la condizione dopo il ciclo while possiamo scambiarlo elsee sbarazzarci di quel controllo.

n = 5
while n > 0:
    print n
    n -= 1
    if n == 2:
        break
else:  # read it as "no_break"
    print n

L'ho sempre letto while/no_breakper capire il codice e questa sintassi ha molto più senso per me.


3

La clausola else viene eseguita solo quando la condizione while diventa falsa.

Ecco alcuni esempi:

Esempio 1: inizialmente la condizione è falsa, quindi viene eseguita la clausola else .

i = 99999999

while i < 5:
    print(i)
    i += 1
else:
    print('this')

PRODUZIONE:

this

Esempio 2: la condizione while i < 5 non è mai diventata falsa perché i == 3interrompe il ciclo, quindi la clausola else non è stata eseguita.

i = 0

while i < 5:
    print(i)
    if i == 3:
        break
    i += 1
else:
    print('this')

PRODUZIONE:

0
1
2
3

Esempio 3: la condizione while è i < 5 diventata falsa quando lo iera 5, quindi è stata eseguita la clausola else .

i = 0

while i < 5:
    print(i)
    i += 1
else:
    print('this')

PRODUZIONE:

0
1
2
3
4
this

0

L' else:istruzione viene eseguita quando e solo quando il ciclo while non soddisfa più la sua condizione (nel tuo esempio, quando n != 0è falso).

Quindi l'output sarebbe questo:

5
4
3
2
1
what the...

Lo so, ma questo tipo di while / else non funziona in Java. Lo trovo piuttosto interessante quando ho capito che funziona in Python. Ero solo curioso e volevo sapere il motivo tecnico.
Ivan,

6
@Ivan: Non è così tanto che non funziona in Java ma che non esiste in Java. Potrebbe essere fatto funzionare se qualcuno si preoccupasse di aggiungerlo alla lingua.
Ignacio Vazquez-Abrams,

1
No, mentre False: .. else .. esegue ancora la clausola else. È più accurato dire: else non viene eseguito solo se il loop viene interrotto.
Leo Ufimtsev,

0

Altrimenti viene eseguito se il ciclo while non si interrompe.

In un certo senso mi piace pensarci con una metafora del "corridore".

L '"altro" è come tagliare il traguardo, indipendentemente dal fatto che tu abbia iniziato all'inizio o alla fine della traccia. "else" non viene eseguito solo se si interrompe un punto intermedio.

runner_at = 0 # or 10 makes no difference, if unlucky_sector is not 0-10
unlucky_sector = 6
while runner_at < 10:
    print("Runner at: ", runner_at)
    if runner_at == unlucky_sector:
        print("Runner fell and broke his foot. Will not reach finish.")
        break
    runner_at += 1
else:
    print("Runner has finished the race!") # Not executed if runner broke his foot.

I casi d'uso principali sono l'utilizzo di questa interruzione dei cicli nidificati o se si desidera eseguire alcune istruzioni solo se il ciclo non si interrompe da qualche parte (si pensi che interrompere sia una situazione insolita).

Ad esempio, il seguente è un meccanismo su come uscire da un ciclo interno senza usare le variabili o provare / catturare:

for i in [1,2,3]:
    for j in ['a', 'unlucky', 'c']:
        print(i, j)
        if j == 'unlucky':
            break
    else: 
        continue  # Only executed if inner loop didn't break.
    break         # This is only reached if inner loop 'breaked' out since continue didn't run. 

print("Finished")
# 1 a
# 1 b
# Finished

-1

L'uso migliore di 'while: else:' la costruzione in Python dovrebbe essere se nessun ciclo viene eseguito in 'while', quindi viene eseguita l'istruzione 'else'. Il modo in cui funziona oggi non ha senso perché puoi usare il codice qui sotto con gli stessi risultati ...

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."

8
No, la differenza è che il elseblocco non verrà eseguito se si esce dal ciclo utilizzando breako la returnparola chiave. Nel tuo esempio, printverrà eseguito anche se il ciclo è terminato a breakcomando.
so cosa fare il

2
Descrivi come la maggior parte delle persone desidera che la funzionalità funzioni, non come funziona davvero!
dotancohen,

-2

È utile per l'interazione sociale.

while (Date != "January 1st"):
    time.sleep(1)
else:
    print("Happy new year!")

2
E qual è esattamente lo scopo del elsequi? Il codice fa esattamente lo stesso senza di esso.
wovano,

Se l'orologio e il calendario breakdurante il conto alla rovescia, il mancato utilizzo elseti farà dire "Felice anno nuovo!" istantaneamente che non ha alcun senso.
Guimoute,

@Guimote, cosa intendi con "se il tuo orologio e calendario break"? Non c'è breaknel codice.
wovano,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.