Else klauzula dotycząca instrukcji Python while

321

Zauważyłem, że następujący kod jest legalny w Pythonie. Moje pytanie brzmi: dlaczego? Czy jest jakiś konkretny powód?

n = 5
while n != 0:
    print n
    n -= 1
else:
    print "what the..."
Ivan
źródło
5
@detly: To dlatego, że większość ludzi unika tej konstrukcji. :) Uważam, że Guido wspomniał podczas procesu Py3k, że przynajmniej wybór tego słowa elsebył wyjątkowo złym pomysłem i że nie robiliby tego więcej.
Nicholas Knight
5
@Nicholas Knight - tak, choć kuszące, prawdopodobnie byłoby to coś, co tylko ja zrozumiałem na pierwszy rzut oka. Każdy inny biedny sok musiałby spojrzeć na specyfikację języka lub cofnąć się w czasie i zadać pytanie tutaj na Sta-heeeeey ...
detly
8
Pomysł wyboru „else” polega na tym, że ta konstrukcja jest podobno często używana w połączeniu z „if X: break” wewnątrz pętli while. Ponieważ klauzula „else” jest wykonywana, jeśli nie wyrwiemy się z pętli, tworzy ona coś w rodzaju „else” w stosunku do „if”.
Jonathan Hartley
12
Powinni to zmienić nazwę after:.
naught101

Odpowiedzi:

388

elseKlauzula jest wykonywana tylko wtedy, gdy whilewarunek stanie się fałszywy. Jeśli wyjdziesz breakz pętli lub zostanie zgłoszony wyjątek, nie zostanie on wykonany.

Jednym ze sposobów myślenia o tym jest konstrukt if / else w odniesieniu do warunku:

if condition:
    handle_true()
else:
    handle_false()

jest analogiczny do konstrukcji zapętlonej:

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

Przykładem może być:

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()
ars
źródło
42
„Klauzula else jest wykonywana tylko wtedy, gdy warunek while jest fałszywy”. Sformułowanie tutaj sugeruje, że twój stan while zmienia się ze stanu true na false i wtedy pozostałe zostaną wykonane. Jeśli jednak chwila nie jest prawdziwa, klauzula else będzie nadal wykonywana.
user597608,
pseudokod Popraw mnie, jeśli się mylę, ale jest to dokładnie to samo, while {} something z wyjątkiem tego, że somethingzostanie pominięty, jeśli będziesz breakw whilepętli.
Daniel Kaplan
2
Być może najdokładniejszym pseudokodem byłoby: while (True) {if (cond) {handle_true (); } else {handle_false (); złamać; }}
VinGarcia
2
„nie przechodź, nie zbieraj 200”, haha, każdy, kto wie, skąd się wzięło, miał dobre dzieciństwo
Stefan Octavian
102

elseKlauzula jest wykonywany po wyjściu bloku normalnie, trafiając warunek pętli lub spadając spód bloku try. To jest nie wykonany, jeśli breaklubreturn z bloku, albo podnieść wyjątek. Działa nie tylko podczas i dla pętli, ale także próbuje blokować.

Zazwyczaj znajduje się w miejscach, w których normalnie wychodziłbyś z pętli wcześniej, a ucieczka z końca pętli jest nieoczekiwaną / nietypową okazją. Na przykład, jeśli przeglądasz listę w poszukiwaniu wartości:

for value in values:
    if value == 5:
        print "Found it!"
        break
else:
    print "Nowhere to be found. :-("
John Kugelman
źródło
1
Właściwie dość przydatny konstrukt dla takiej rzeczy. Nie wiem, ile razy umieszczałem found_it=Falsena początku pętli, a potem sprawdzałem, czy found_itpod koniec
Cruncher
42

W odpowiedzi na Is there a specific reason?to jest jedna interesująca aplikacja: przełamanie wielu poziomów zapętlenia.

Oto jak to działa: zewnętrzna pętla ma przerwę na końcu, więc zostanie wykonana tylko raz. Jeśli jednak wewnętrzna pętla się zakończy (nie znajdzie dzielnika), wówczas osiągnie wyrażenie else i zewnętrzna przerwa nigdy nie zostanie osiągnięta. W ten sposób przerwa w wewnętrznej pętli wyrwie się z obu pętli, a nie tylko z jednej.

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!'

Dla obu whilei forpętle The elseinstrukcja wykonywana jest na końcu, chyba że breakużyto.

W większości przypadków istnieją lepsze sposoby na zrobienie tego (zawijanie go w funkcję lub zgłaszanie wyjątku), ale to działa!

znak
źródło
1
Nie głosowałem, ale myślę, że wiem, dlaczego ktoś to zrobił. Nie odpowiadasz na pytanie i podajesz 14 linii kodu z tylko 2 liniami opisu. Jeśli ma to związek z zadanym pytaniem, nie mówisz nam ...
BlueEel
1
@BlueEel dzięki za opinie! Dodałem więcej wyjaśnień na temat kodu i wyjaśniłem, w jaki sposób odpowiada na pytanie (ponieważ odpowiada na część tego pytania).
Mark
Udało ci się umieścić swój kod w kontekście i chociaż nie odpowiadasz na wszystkie pytania, teraz widzę, że ma to znaczenie. Poparłem twoją odpowiedź, ponieważ jest ona teraz przydatna dla początkujących i nowicjuszy (jak ja w odniesieniu do pytona). - Dzięki, nauczyłem się czegoś.
BlueEel,
Podoba mi się prosta aplikacja - teraz rozumiem, dlaczego ktoś może z niej skorzystać. Chociaż nigdy nie widziałem takiej potrzeby.
gabe
Przykład pokazuje użycie for / else, ale pytanie dotyczyło konkretnie while / else.
Ian Goldby
20

Klauzula else jest wykonywana, gdy warunek while ma wartość false.

Z dokumentacji :

Instrukcja while służy do wielokrotnego wykonywania, dopóki prawdziwe jest wyrażenie:

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

Powoduje to wielokrotne testowanie wyrażenia i, jeśli jest to prawdą, wykonanie pierwszego pakietu; jeśli wyrażenie jest fałszywe (co może być pierwszym testem), zestaw elseklauzuli, jeśli jest obecny, jest wykonywany i pętla kończy się.

breakOświadczenie wykonany w pierwszej pakietu kończy pętlę bez wykonywania elsepakiet klauzula jest. continueOświadczenie wykonany w pierwszej pakietu pomija resztę pakietu i wraca do testowania ekspresji.

Mark Rushakoff
źródło
15

Moja odpowiedź skupi się na KIEDY możemy użyć podczas / na-innym.

Na pierwszy rzut oka wydaje się, że nie ma różnicy w użyciu

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

i

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

Ponieważ print 'ELSE'instrukcja wydaje się zawsze wykonywana w obu przypadkach (zarówno po zakończeniu whilepętli, jak i po jej uruchomieniu).

Wtedy będzie inaczej tylko wtedy, gdy instrukcja print 'ELSE'nie zostanie wykonana. To wtedy, gdy breakpod blokiem znajduje się blok koduwhile

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

Jeśli różnią się od:

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 nie jest w tej kategorii, ponieważ ma ten sam efekt w dwóch powyższych przypadkach.

zgłaszanie wyjątków również nie powoduje różnicy, ponieważ gdy zgłoszenie zostanie wykonane, w którym następny kod zostanie wykonany, jest on obsługiwany w wyjątku (oprócz bloku), kod w elseklauzuli lub bezpośrednio po niej whilenie zostanie wykonany.

HVNSweeting
źródło
4

Wiem, że to stare pytanie, ale ...

Jak powiedział Raymond Hettinger, należy go wywołać while/no_breakzamiast while/else.
Łatwo to zrozumieć, jeśli spojrzysz na ten fragment kodu.

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

Teraz zamiast sprawdzania stanu po pętli while możemy go zamienić elsei pozbyć się tego sprawdzania.

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

Zawsze czytam go, while/no_breakaby zrozumieć kod, a ta składnia ma dla mnie znacznie większy sens.

Iluvatar
źródło
3

Klauzula else jest wykonywana tylko wtedy, gdy warunek while staje się fałszywy.

Oto kilka przykładów:

Przykład 1: Początkowo warunek jest fałszywy, więc klauzula else jest wykonywana.

i = 99999999

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

WYNIK:

this

Przykład 2: natomiast warunek i < 5 nigdy nie stał się fałszywe, ponieważ i == 3łamie pętli, więc jeszcze klauzula nie została wykonana.

i = 0

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

WYNIK:

0
1
2
3

Przykład 3: natomiast warunkiem i < 5 się fałszywie gdy ibył 5tak dalej klauzula została wykonana.

i = 0

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

WYNIK:

0
1
2
3
4
this
Saif Ur Rahman
źródło
0

else:Instrukcja wykonywana jest wtedy i tylko wtedy, gdy pętla gdy nie spełnia już jej stan (w przykładzie, jeśli n != 0jest fałszywe).

Wynik byłby następujący:

5
4
3
2
1
what the...
BoltClock
źródło
Wiem, ale ten rodzaj czasu / else nie działa w Javie. Uważam, że jest to dość interesujące, kiedy zorientowałem się, że działa w Pythonie. Byłem po prostu ciekawy i chciałem poznać przyczynę techniczną.
Ivan
6
@Ivan: To nie tyle, że nie działa w Javie, ale że nie istnieje w Javie. Można go uruchomić, jeśli ktoś zechce dodać go do języka.
Ignacio Vazquez-Abrams
1
Nie, podczas gdy False: .. else .. nadal działa klauzula else. Mówiąc dokładniej: w przeciwnym razie pętla nie zostanie uruchomiona, jeśli pętla zostanie przerwana.
Leo Ufimtsev
0

W przeciwnym razie pętla while nie ulegnie awarii.

Lubię myśleć o tym z metaforą „biegacza”.

„Else” jest jak przekroczenie linii mety, bez względu na to, czy zacząłeś na początku, czy na końcu toru. „else” nie jest wykonywane tylko wtedy, gdy złamiesz się gdzieś pomiędzy.

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.

Główne przypadki użycia polegają na przełamywaniu zagnieżdżonych pętli lub jeśli chcesz uruchomić niektóre instrukcje tylko wtedy, gdy pętla gdzieś się nie zepsuła (pomyśl o zerwaniu jako nietypowej sytuacji).

Na przykład poniżej przedstawiono mechanizm wyjścia z wewnętrznej pętli bez użycia zmiennych lub try / catch:

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
Lew Ufimcew
źródło
-1

Lepszym zastosowaniem konstrukcji „while: else:” w Pythonie powinno być, jeśli żadna pętla nie jest wykonywana w „while”, wówczas wykonywana jest instrukcja „else”. Dzisiejszy sposób nie ma sensu, ponieważ możesz użyć poniższego kodu z tymi samymi wynikami ...

n = 5
while n != 0:
    print n
    n -= 1
print "what the..."
Jean Ferri
źródło
8
Nie, różnica polega na tym, że elseblok nie zostanie wykonany, jeśli opuścisz pętlę za pomocą breaklub returnsłowa kluczowego. W twoim przykładzie printzostanie wykonane również, jeśli pętla zakończy się na breakkomendzie.
notsurewhattodo
2
Opisujesz, jak większość ludzi chce, aby ta funkcja działała, a nie jak to działa!
dotancohen
-2

Jest to przydatne do interakcji społecznych.

while (Date != "January 1st"):
    time.sleep(1)
else:
    print("Happy new year!")
Guimoute
źródło
2
A jaki jest dokładnie cel tego else? Kod robi dokładnie to samo bez niego.
wovano,
Jeśli breakpodczas odliczania zegar i kalendarz nieużywanie elsesprawi, że powiesz „Szczęśliwego nowego roku!” natychmiast, co nie ma żadnego sensu.
Guimoute,
@Guimote, co masz na myśli przez „jeśli twój zegar i kalendarz break”? Nie ma breakw kodzie.
wovano,