Dlaczego Python używa pętli „else” po pętli for i while?

480

Rozumiem, jak działa ten konstrukt:

for i in range(10):
    print(i)

    if i == 9:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

Ale nie rozumiem, dlaczego elseużyto tutaj słowa kluczowego, ponieważ sugeruje, że dany kod działa tylko wtedy, gdy forblok nie zostanie ukończony, co jest przeciwieństwem tego, co robi! Bez względu na to, jak o tym myślę, mój mózg nie może płynnie przechodzić od forwypowiedzi do elsebloku. Dla mnie, continueczy continuewithmiałoby to więcej sensu (i staram się trenować, aby czytać to jako takie).

Zastanawiam się, jak kodery Pythona odczytują ten konstrukt w swojej głowie (lub głośno, jeśli chcesz). Być może brakuje mi czegoś, co ułatwiłoby rozszyfrowanie takich bloków kodu?

Kent Boogaart
źródło
26
Może chcesz przetłumaczyć to na „wtedy” w twojej głowie.
Marcin
63
Nie zapominaj o kluczowej linii w Zen Pythona: „... początkowo taki sposób może nie być oczywisty, chyba że jesteś Holendrem”.
Daniel Roseman,
50
W mojej głowie tłumaczę to na „jeśli nie złamać” . A ponieważ breakjest często używany w pętlach „znalazłem to” , możesz przetłumaczyć go na „jeśli nie znaleziono” , co nie jest dalekie od tego, co elseczyta
MestreLion
29
Myślę, że prawdziwym pytaniem wielu ludzi jest: „Jaka jest różnica między for ... else foo()po prostu wprowadzeniem foo()pętli for?”. Odpowiedź brzmi: zachowują się inaczej tylko wtedy, gdy pętla zawiera break(jak opisano szczegółowo poniżej).
Sam Kauffman,
10
Średnik w pytonie ... bolą mnie oczy ... mimo że jest poprawny pod względem składniowym, nie jest to dobrą praktyką
DarkCygnus

Odpowiedzi:

277

To dziwna konstrukcja nawet dla doświadczonych programistów Pythona. W połączeniu z pętlami for oznacza po prostu „znajdź jakiś element w iteracji, w przeciwnym razie, jeśli żaden nie zostanie znaleziony, wykonaj…”. Jak w:

found_obj = None
for obj in objects:
    if obj.key == search_key:
        found_obj = obj
        break
else:
    print('No object found.')

Ale za każdym razem, gdy zobaczysz ten konstrukt, lepszą alternatywą jest albo kapsułkowanie wyszukiwania w funkcji:

def find_obj(search_key):
    for obj in objects:
        if obj.key == search_key:
            return obj

Lub skorzystaj ze zrozumienia listy:

matching_objs = [o for o in objects if o.key == search_key]
if matching_objs:
    print('Found {}'.format(matching_objs[0]))
else:
    print('No object found.')

Nie jest semantycznie równoważny z pozostałymi dwiema wersjami, ale działa wystarczająco dobrze w niekrytycznym kodzie krytycznym, gdzie nie ma znaczenia, czy iterujesz całą listę, czy nie. Inni mogą się nie zgadzać, ale ja osobiście unikałbym używania bloków for-else lub while-else w kodzie produkcyjnym.

Zobacz także [Python-ideas] Podsumowanie dla ... innych wątków

Björn Lindqvist
źródło
50
Zrozumienie listy jest niewłaściwe. Jeśli szukasz pojedynczego elementu, jak w forprzykładach z pętli, i chcesz użyć wyrażenia / listy do generatora, to next((o for o in objects if o.key == search_key), None)lub zawiń go w try/ excepti nie używaj wartości domyślnej zamiast if/ else.
agf
4
i podobnie jak odpowiedź Lance Helsten, istnieją rzeczywiste przypadki, w których lepiej jest użyć for/elsekonstruktu.
Andre
5
Twoje zdrowie. Miałem źle wcięte akta, w których elsesparowałem się z fori nie miałem pojęcia, że ​​to legalne.
maxywb
3
Myślę, że pętla for jest najbardziej oczywistą z tamtejszych konstrukcji.
Miles Rout
14
Warto wspomnieć, że klauzula else będzie działać, nawet jeśli pętla for ma wartości, chyba że breakinstrukcja działa w trybie jawności, jak w tym przykładzie. Z powyższych dokumentów: „ elseKlauzula ma inny dostrzegany problem: jeśli nie ma jej breakw pętli, elseklauzula jest funkcjonalnie redundantna.”. np.for x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
dhackner
586

Typową konstrukcją jest uruchamianie pętli, dopóki coś nie zostanie znalezione, a następnie wyrwanie się z pętli. Problem polega na tym, że jeśli wyjdę z pętli lub końców pętli, muszę ustalić, który przypadek się wydarzył. Jedną z metod jest stworzenie zmiennej flag lub store, która pozwoli mi wykonać drugi test, aby zobaczyć, jak pętla została zamknięta.

Załóżmy na przykład, że muszę przeszukać listę i przetworzyć każdy element, aż zostanie znaleziony element flagi, a następnie przerwać przetwarzanie. Jeśli brakuje elementu flagi, należy zgłosić wyjątek.

Korzystając z konstrukcji Pythona for... elsemasz

for i in mylist:
    if i == theflag:
        break
    process(i)
else:
    raise ValueError("List argument missing terminal flag.")

Porównaj to z metodą, która nie używa tego cukru syntaktycznego:

flagfound = False
for i in mylist:
    if i == theflag:
        flagfound = True
        break
    process(i)

if not flagfound:
    raise ValueError("List argument missing terminal flag.")

W pierwszym przypadku raisejest ściśle związany z pętlą for, z którą współpracuje. W drugim przypadku wiązanie nie jest tak silne i podczas konserwacji można wprowadzić błędy.

Lance Helsten
źródło
69
To wyjaśnia to lepiej niż wybrana odpowiedź, w której autor tak naprawdę nie rozumie, o co chodzi!
erikbwork
17
Muszę powiedzieć, że ten cukier syntaktyczny może zepsuć zęby twojego projektu. To nie byłoby Python: the good partsksiążka.
Boatcoder
1
Czy możesz potwierdzić, że w twoim process(i)przypadku zdarza się to dla każdego przedmiotu mylistwcześniej theflag, a nie dla theflagsiebie? Czy to jest to, co było zamierzone?
bli
4
processwykona się na każdym, iktóry istnieje na liście przed theflagosiągnięciem, nie zostanie wykonany na elementach na liście później theflagi nie zostanie wykonany theflag.
Lance Helsten
1
instrukcja else jest również wykonywana, jeśli iterowalny nie ma elementów
Lost Crotchet
173

Istnieje doskonała prezentacja Raymonda Hettingera, zatytułowana Transforming Code into Beautiful, Idiomatic Python , w której krótko omawia historię for ... elsekonstruktu. Odpowiednią sekcją jest „Rozróżnianie wielu punktów wyjścia w pętlach”, zaczynając od 15:50 i kontynuując przez około trzy minuty. Oto najważniejsze punkty:

  • for ... elseKonstrukt został opracowany przez Donald Knuth jako zamiennik dla niektórych GOTOprzypadków zastosowania;
  • Ponowne wykorzystanie elsesłów kluczowych sens, ponieważ „to, co kiedyś Knuth, a ludzie wiedzieli, w tym czasie, wszystkie [ forwypowiedzi] był osadzony ifi GOTOpod spodem, i oczekuje się, że else”;
  • Z perspektywy czasu powinno się to nazywać „bez przerwy” (lub „nobreak”), a wtedy nie byłoby to mylące. *

Więc jeśli pytanie brzmi: „Dlaczego nie zmienią tego słowa kluczowego?” wtedy Cat Plus Plus prawdopodobnie udzielił najdokładniejszej odpowiedzi - w tym momencie byłoby to zbyt destrukcyjne dla istniejącego kodu, aby było praktyczne. Ale jeśli pytanie, które naprawdę zadajesz, brzmi: dlaczego elsezostało ponownie użyte, cóż, najwyraźniej wydawało się to wtedy dobrym pomysłem.

Osobiście podoba mi się kompromis polegający na komentowaniu # no breakw miejscu, gdzie elsena pierwszy rzut oka można się pomylić z przynależnością do pętli. Jest dość jasny i zwięzły. Ta opcja otrzymuje krótką wzmiankę w podsumowaniu, do którego Bjorn podłączył na końcu swojej odpowiedzi:

Dla kompletności powinienem wspomnieć, że przy niewielkiej zmianie składni programiści, którzy chcą tej składni, mogą ją teraz mieć:

for item in sequence:
    process(item)
else:  # no break
    suite

* Cytat bonusowy z tej części filmu: „Tak jak gdybyśmy nazwali funkcję makrofagów, nikt nie zapytałby:„ Co robi lambda? ”.

Powietrze
źródło
33

Ponieważ nie chcieli wprowadzić nowego słowa kluczowego do języka. Każdy z nich kradnie identyfikator i powoduje problemy ze zgodnością wsteczną, więc zwykle jest to ostateczność.

Cat Plus Plus
źródło
2
Wydaje się, finallyże w takim przypadku byłby lepszy wybór. Czy w chwili wprowadzenia tego konstruktu słowo kluczowe nie było jeszcze obecne?
Ponkadoodle
26
@Wallacoloo finallynie jest dużo lepszy, ponieważ sugeruje, że blok będzie zawsze wykonywany po pętli, a tak nie jest (ponieważ byłoby to zbędne po prostu uruchamiając kod po pętli).
Cat Plus Plus
Nie może też być tak, finallyponieważ klauzula else jest wykonywana także wtedy, gdy continuejest używana w pętli for - to możliwe, że wiele razy i nie tylko na końcu.
pepr
6
Na elsewykonanie klauzuli @pepr nie ma wpływu continue( dokumenty i kod testowy )
Air
@AirThomas: +1. Masz rację. elseJest wykonywana tylko wtedy, gdy continuebył jednym z ostatniej iteracji.
pepr
33

Upraszczając, możesz tak o tym myśleć;

  • Jeśli napotka breakpolecenie w forpętli, elseczęść nie zostanie wywołana.
  • Jeśli nie napotka breakpolecenia w forpętli, elseczęść zostanie wywołana.

Innymi słowy, jeśli iteracja pętli nie zostanie „zerwana” break, elseczęść zostanie wywołana.

Ad Infinitum
źródło
elseBlok również nie będą wykonywane, jeżeli korpus pętli zgłasza wyjątek.
Amal K
17

Najłatwiejszym sposobem, aby „dostać” to, co zrobił for / else, a co ważniejsze, kiedy go użyć, było skoncentrowanie się na tym, do czego przeskakuje instrukcja break. Konstrukcja For / else jest pojedynczym blokiem. Przerwa wyskakuje z bloku i przeskakuje „nad” klauzulą ​​else. Gdyby treść klauzuli else była po prostu zgodna z klauzulą ​​for, nigdy nie byłaby przeskakiwana, więc należałoby podać równoważną logikę, umieszczając ją w if. To zostało powiedziane wcześniej, ale nie do końca w tych słowach, więc może pomóc komuś innemu. Spróbuj uruchomić następujący fragment kodu. Z całego serca opowiadam się za komentarzem „bez przerwy” za jasność.

for a in range(3):
    print(a)
    if a==4: # change value to force break or not
        break
else: #no break  +10 for whoever thought of this decoration
    print('for completed OK')

print('statement after for loop')
Neil_UK
źródło
„Przerwa wyskakuje z bloku, a zatem przeskakuje„ nad ”klauzulą ​​else - chociaż może to być pomocne jako sposób na„ uzyskanie ” for:/ else:, tak naprawdę nie uzasadnia tego słowa kluczowego else. Biorąc pod uwagę ramy podane tutaj, then:wydaje się, że byłoby to znacznie bardziej naturalne. (Nie powody do elsebycia wybranym, podane w innych odpowiedzi - nie są one tylko pod warunkiem, tutaj.)
Mark Amery
16

Myślę, że dokumentacja zawiera świetne wyjaśnienie innych kwestii , kontynuuj

[...] jest wykonywany, gdy pętla kończy się przez wyczerpanie listy (z for) lub gdy warunek staje się fałszywy (z while), ale nie wtedy, gdy pętla jest kończona przez instrukcję break. ”

Źródło: Dokumentacja Python 2: Samouczek dotyczący przepływu sterowania

Ayan
źródło
13

Przeczytałem coś w stylu:

Jeśli jeszcze warunków do uruchomienia pętli, robić rzeczy, jeszcze coś innego.

pcalcao
źródło
Twoje warunki nadal są pomocne (+1), chociaż są złe - to ludzkie ;-)
Wolf
-1; ta wymowa for:/ else:sprawia, że ​​brzmi to tak, jakby else:zawsze działało po pętli, co nie jest prawdą.
Mark Amery
11

Ponieważ na część techniczną udzielono odpowiedzi, mój komentarz jest po prostu związany z zamieszaniem, które wywołuje to słowo kluczowe z recyklingu .

Ponieważ Python jest bardzo wymownym językiem programowania, niewłaściwe użycie słowa kluczowego jest bardziej znane. elseKluczowe doskonale opisuje część strumienia drzewa decyzyjnego „jeśli nie można to zrobić, (jeszcze) zrobić”. Jest to sugerowane w naszym własnym języku.

Zamiast tego użycie tego słowa kluczowego z instrukcjami whilei forpowoduje zamieszanie. Powód, dla którego nasza kariera programistów nauczyła nas, że elseoświadczenie znajduje się w drzewie decyzyjnym; jego zakres logiczny , opakowanie, które warunkowo zwraca ścieżkę do naśladowania. Tymczasem instrukcje pętli mają konkretny, wyraźny cel, aby coś osiągnąć. Cel jest osiągany po ciągłej iteracji procesu.

if / else wskaż ścieżkę, którą chcesz podążać . Pętle podążają ścieżką aż do osiągnięcia „celu” .

Problem polega na tym, że elsejest to słowo, które jasno definiuje ostatnią opcję w warunku. W semantykę tego słowa są zarówno dzielone przez Python i Human Language. Ale słowo „inaczej” w języku ludzkim nigdy nie jest używane do wskazania działań, które ktoś lub coś podejmie po zakończeniu. Zostanie wykorzystany, jeśli w trakcie jego uzupełniania pojawi się problem (bardziej jak instrukcja break ).

Na koniec słowo kluczowe pozostanie w języku Python. Jest jasne, że to był błąd, wyraźniej, gdy każdy programista próbuje wymyślić historię, aby zrozumieć jej użycie jak jakieś urządzenie mnemoniczne. Bardzo bym chciał, gdyby zamiast tego wybrali słowo kluczowe then. Uważam, że to słowo kluczowe idealnie pasuje do tego iteracyjnego przepływu, który jest opłacalny po pętli.

Przypomina to sytuację, którą ma dziecko po każdym kroku montażu zabawki: A NASTĘPNIE tato?

3rdWorldCitizen
źródło
Myślę, że ta odpowiedź rozwiązuje problem zamieszania, o którym myślę, że OP mówił. Słowo kluczowe else robi dokładnie odwrotność tego, czego można oczekiwać od angielskiego znaczenia else, gdy jest dołączone do działania for. Teoretycznie for ... else mógł działać inaczej, ponieważ kończysz się w części else, gdy pęka się pętlę, ale problem polega na tym, że można go użyć do znalezienia elementu x i obsłużenia przypadku, w którym x nie znaleziono, być może będziesz musiał użyć flagi lub innego testu po całości dla .. else
build
7

Przeczytałem to tak, jak: „Gdy iterablecałkowicie się wyczerpie, a wykonanie zakończy się po następnej instrukcji for, klauzula else zostanie wykonana”. Zatem, gdy iteracja zostanie przerwana break, nie zostanie to wykonane.

0xc0de
źródło
6

Zgadzam się, to bardziej jak „elif nie [warunek (y) podnoszenia przerwy]”.

Wiem, że to stary wątek, ale teraz zastanawiam się nad tym samym pytaniem i nie jestem pewien, czy ktoś uchwycił odpowiedź na to pytanie w sposób, w jaki je rozumiem.

Dla mnie istnieją trzy sposoby „czytania” THE elsesię For... elselub While... elseoświadczenia, z których wszystkie są równoważne, to:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (przypuszczalnie jest taki warunek, inaczej nie miałbyś pętli)

Zasadniczo „else” w pętli jest tak naprawdę „elif ...”, gdzie „...” oznacza (1) brak przerwy, co jest równoważne (2) NIE [warunkowi (-om) podniesienia przerwy].

Myślę, że kluczem jest to, że nie elsema sensu bez „przerwy”, więc a for...elseobejmuje:

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

Tak więc podstawowe elementy for...elsepętli są następujące i można je czytać w prostszym języku angielskim jako:

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

Jak powiedzieli inni plakaty, przerwa jest generalnie generowana, gdy jesteś w stanie zlokalizować to, czego szuka twoja pętla, więc else:staje się „co zrobić, jeśli nie można zlokalizować elementu docelowego”.

Przykład

Możesz także używać obsługi wyjątków, przerw i pętli.

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

Wynik

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

Przykład

Prosty przykład z uderzeniem przerwy.

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

Wynik

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

Przykład

Prosty przykład, w którym nie występuje przerwa, brak warunku podniesienia przerwy i nie występuje błąd.

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

Wynik

z: 0
z: 1
z: 2
z_loop complete without break or error
----------
NotAnAmbiTurner
źródło
6

elseKluczowe może być tu mylące, i jak wiele osób podkreśliło, coś podobnego nobreak, notbreakjest bardziej odpowiednie.

Aby zrozumieć for ... else ...logicznie, porównaj to z try...except...else, nie if...else..., większość programistów pythonowych zna następujący kod:

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

Podobnie pomyśl o breakszczególnym rodzaju Exception:

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

Różnica jest pythonimplikowana except breaki nie można jej zapisać, więc staje się:

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

Tak, wiem, że to porównanie może być trudne i męczące, ale wyjaśnia zamieszanie.

cizixs
źródło
Powinieneś zrobić link do zasobu, kiedy go kopiujesz: Notatki Nicka Coghlana w Pythonie .
godaygo
@godaygo dzięki za link. Czytam i akceptuję tę koncepcję przy pierwszej nauce języka Python, nie zapamiętywałam źródła podczas pisania odpowiedzi.
cizixs
@cizixs „Nie zapamiętałeś źródła”, ale akurat zawierałeś całe zdania komentarzy identyczne z oryginałem? Ooookaaaay.
Mark Amery
5

Kody w elsebloku instrukcji zostaną wykonane, gdy forpętla nie zostanie przerwana.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

Z dokumentacji: przerywaj i kontynuuj Instrukcje, a także Klauzule dotyczące pętli

Instrukcje pętli mogą zawierać klauzulę else; jest wykonywany, gdy pętla kończy się przez wyczerpanie listy (z for) lub gdy warunek staje się fałszywy (z while), ale nie wtedy, gdy pętla jest kończona przez instrukcję break. Przykładem jest następująca pętla, która wyszukuje liczby pierwsze:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Tak, to jest poprawny kod. Przyjrzyj się uważnie: klauzula else należy do pętli for, a nie do instrukcji if).

W przypadku użycia z pętlą klauzula else ma więcej wspólnego z klauzulą ​​else instrukcji try niż z instrukcją if: klauzula else instrukcji try działa, gdy nie występuje wyjątek, a klauzula else działa, gdy nie następuje przerwa . Aby uzyskać więcej informacji na temat instrukcji try i wyjątków, zobacz Obsługa wyjątków.

Instrukcja kontynuacji, również zapożyczona z C, kontynuuje następną iterację pętli:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
Idąc moją drogą
źródło
1
To nic nie dodaje i nie odpowiada na pytanie, które nie jest jak, ale dlaczego .
Air
5

Oto sposób, aby pomyśleć o tym, o czym nikt inny nie wspominał powyżej:

Po pierwsze, pamiętaj, że pętle for to po prostu cukier syntaktyczny wokół pętli while. Na przykład pętla

for item in sequence:
    do_something(item)

można przepisać (w przybliżeniu) jako

item = None
while sequence.hasnext():
    item = sequence.next()
    do_something(item)

Po drugie, pamiętaj, że pętle while są w zasadzie powtarzanymi blokami if! Zawsze możesz odczytać pętlę while jako „jeśli ten warunek jest spełniony, wykonaj treść, a następnie wróć i sprawdź ponownie”.

Tak więc, podczas gdy / else ma doskonały sens: jest to dokładnie taka sama struktura, jak w przypadku / else, z dodatkową funkcją zapętlania, aż warunek stanie się fałszywy, zamiast tylko sprawdzać warunek raz.

I wtedy for / else ma również sens: ponieważ wszystkie pętle for są po prostu cukrem syntaktycznym na szczycie pętli while, wystarczy dowiedzieć się, jakie są ukryte warunki warunkowe pętli while, a wtedy pozostałe odpowiada, kiedy to stan staje się Fałszywy.

Aaron Gable
źródło
4

Świetne odpowiedzi to:

  • ten , który wyjaśnia historię i
  • to daje prawo cytowania, aby złagodzić swoje tłumaczenie / zrozumienia.

Moja notatka pochodzi z tego, co powiedział kiedyś Donald Knuth (przepraszam, nie mogę znaleźć odniesienia), że istnieje konstrukcja, w której while-else jest nie do odróżnienia od if-else, a mianowicie (w Pythonie):

x = 2
while x > 3:
    print("foo")
    break
else:
    print("boo")

ma taki sam przepływ (z wyłączeniem różnic niskiego poziomu) jak:

x = 2
if x > 3:
    print("foo")
else:
    print("boo")

Chodzi o to, że if-else może być uważany za cukier składniowy dla while-else, który ukryty jest breakna końcu jego ifbloku. Przeciwna implikacja, że ​​ta whilepętla jest przedłużeniem if, jest bardziej powszechna (jest to po prostu powtarzanie / zapętlona kontrola warunkowa), ponieważ ifczęsto jest nauczana wcześniej while. Nie jest to jednak prawdą, ponieważ oznaczałoby to elseblokowanie w czasie, w którym -w przeciwnym razie byłby wykonywany za każdym razem, gdy warunek jest fałszywy.

Aby ułatwić ci zrozumienie, pomyśl o tym w ten sposób:

Bez break, returnitd końce pętli tylko wtedy, gdy warunek nie jest już prawdą, a w takim przypadku elsebloku będzie również wykonać tylko raz. W przypadku Pythona formusisz wziąć pod uwagę forpętle w stylu C (z warunkami) lub przetłumaczyć je na while.

Kolejna uwaga:

Przedwczesny break, returnitp pętli wewnątrz uniemożliwia warunek, by stać się fałszywe, ponieważ wykonanie wyskoczyła z pętli while warunek był prawdziwy i nigdy nie wróci, by sprawdzić go ponownie.

WloHu
źródło
3

Możesz pomyśleć o tym tak, elsejak w pozostałej części lub o innych rzeczach, które nie zostały zrobione w pętli.

jamylak
źródło
3
for i in range(3):
    print(i)

    if i == 2:
        print("Too big - I'm giving up!")
        break;
else:
    print("Completed successfully")

„else” tutaj jest szalenie proste, po prostu wredne

1, „jeśli for clauseukończono”

for i in range(3):
    print(i)

    if i == 2:
        print("Too big - I'm giving up!")
        break;
if "for clause is completed":
    print("Completed successfully")

Potrafi pisać tak długie stwierdzenia, że ​​„klauzula jest zakończona”, więc wprowadzają „else”.

else tutaj jest w swojej naturze.

2, ale co powiesz na for clause is not run at all

In [331]: for i in range(0):
     ...:     print(i)
     ...: 
     ...:     if i == 9:
     ...:         print("Too big - I'm giving up!")
     ...:         break
     ...: else:
     ...:     print("Completed successfully")
     ...:     
Completed successfully

Więc to całkowicie stwierdzenie jest kombinacją logiczną:

if "for clause is completed" or "not run at all":
     do else stuff

lub ujmując to w ten sposób:

if "for clause is not partially run":
    do else stuff

lub w ten sposób:

if "for clause not encounter a break":
    do else stuff
Rachunek różniczkowy
źródło
w przeciwnym razie działa w SQL jako „transakcja”.
Rachunek
2

Oto kolejny idiomatyczny przypadek użycia oprócz wyszukiwania. Powiedzmy, że chcesz poczekać na spełnienie warunku, np. Otwarcie portu na zdalnym serwerze wraz z pewnym czasem oczekiwania. Następnie możesz użyć takiej while...elsekonstrukcji:

import socket
import time

sock = socket.socket()
timeout = time.time() + 15
while time.time() < timeout:
    if sock.connect_ex(('127.0.0.1', 80)) is 0:
        print('Port is open now!')
        break
    print('Still waiting...')
else:
    raise TimeoutError()
Jonathan Sudiaman
źródło
1

Chciałem po prostu znów to zrozumieć. Odkryłem, że następujące pomaga!

• Pomyśl o elsesparowaniu z ifwewnętrzną pętlą (zamiast z for) - jeśli warunek jest spełniony, przerwij pętlę, w przeciwnym razie zrób to - z wyjątkiem tego, że jest elsesparowany z wieloma ifs!
• Jeśli nie ma żadnych ifsatysfakcji, zrób to else.
• Wielokrotność ifs może być również uważana za if- elifs!

Germaine Goh
źródło
-2

Uważam strukturę jak w przypadku (jeśli) A inny B, a dla (jeśli) -else jest specjalny if-else , z grubsza . Może pomóc zrozumieć inaczej .

A i B są wykonywane najwyżej raz, co jest tym samym co struktura if-else.

for (if) można uznać za specjalny if, który wykonuje pętlę, aby spróbować spełnić warunek if. Gdy warunek if zostanie spełniony, A i przerwać ; Else , B.

Jie Zhang
źródło
-2

Python używa pętli „for za” i „while”, więc jeśli nic nie dotyczy pętli, dzieje się coś innego. Na przykład:

test = 3
while test == 4:
     print("Hello")
else:
     print("Hi")

Wynik byłby „Cześć” w kółko (jeśli mam rację).

Mrmongoose64
źródło