Wie kann ich die "else" -Klausel von Python-Schleifen verstehen?

191

Viele Python-Programmierer wissen wahrscheinlich nicht, dass die Syntax von whileSchleifen und forSchleifen eine optionale else:Klausel enthält:

for val in iterable:
    do_something(val)
else:
    clean_up()

Der Hauptteil der elseKlausel ist ein guter Ort für bestimmte Arten von Bereinigungsaktionen und wird bei normaler Beendigung der Schleife ausgeführt: Dh Verlassen der Schleife mit returnoder breakÜberspringen der elseKlausel; Beenden nach einem continueführt es aus. Ich weiß das nur, weil ich es gerade (noch einmal) nachgeschlagen habe , weil ich mich nie erinnern kann, wann die elseKlausel ausgeführt wird.

Immer? Bei "Ausfall" der Schleife, wie der Name schon sagt? Bei regelmäßiger Kündigung? Auch wenn die Schleife mit beendet wird return? Ich kann nie ganz sicher sein, ohne es nachzuschlagen.

Ich beschuldige meine anhaltende Unsicherheit mit der Wahl des Schlüsselworts: Ich finde elsediese Semantik unglaublich unmnemonisch. Meine Frage lautet nicht "Warum wird dieses Schlüsselwort für diesen Zweck verwendet" (für das ich wahrscheinlich stimmen würde, wenn auch nur nach dem Lesen der Antworten und Kommentare), sondern wie kann ich über das elseSchlüsselwort nachdenken, damit seine Semantik Sinn macht, und ich kann mich also daran erinnern?

Ich bin mir sicher, dass darüber ziemlich viel diskutiert wurde, und ich kann mir vorstellen, dass die Wahl aus Gründen der Übereinstimmung mit der Klausel der tryErklärung else:(die ich auch nachschlagen muss) und mit dem Ziel getroffen wurde, nicht zur Liste von hinzuzufügen Pythons reservierte Worte. Vielleicht elseklären die Gründe für die Wahl seine Funktion und machen es einprägsamer, aber ich bin, nachdem ich den Namen mit der Funktion verbunden habe, nicht nach der historischen Erklärung an sich.

Die Antworten auf diese Frage , deren Frage kurz als Duplikat geschlossen wurde, enthalten viele interessante Hintergrundgeschichten. Meine Frage hat einen anderen Schwerpunkt (wie man die spezifische Semantik von elsemit der Keyword-Auswahl verbindet), aber ich denke, es sollte irgendwo einen Link zu dieser Frage geben.

alexis
quelle
23
Wie wäre es mit "wenn noch etwas zu iterieren ist ... sonst"
OneCricketeer
4
Ich denke, Sie können sich jetzt daran erinnern, nachdem Sie diese Frage geschrieben haben :)
Jasper
11
das elsebedeutet im Grunde "wenn die Fortsetzungsbedingung fehlschlägt". In einer traditionellen for-Schleife ist die Fortsetzungsbedingung normalerweise i < 42. In diesem Fall können Sie diesen Teil alsif i < 42; execute the loop body; else; do that other thing
njzk2
1
Das ist alles wahr, und ich mag besonders drawoc Antwort, aber eine andere Sache ist zu berücksichtigen , dass sonst ein verfügbares Schlüsselwort ist , dass auch syntaxically etwas gut macht Sinn. Sie wissen vielleicht, dass Sie versuchen / außer und vielleicht versuchen / außer / endlich, aber es hat auch sonst - führen Sie diesen Code aus, wenn keine Ausnahme aufgetreten ist. Das ist übrigens nicht dasselbe wie das Verschieben dieses Codes unter die try-Klausel - die Ausnahmebehandlung wird am besten verwendet, wenn sie eng ausgerichtet ist. Obwohl es konzeptionell sinnvoll ist - wie aus einer Reihe von Antworten hier hervorgeht -, denke ich, dass es auch die Wiederverwendung von Schlüsselwörtern im Spiel ist, führen Sie dies unter bestimmten Bedingungen aus .
JL Peyret
1
@Falanwe, es gibt einen Unterschied, wenn der Code von beendet wird break. Der kanonische Anwendungsfall ist, wenn die Schleife nach etwas sucht und bricht, wenn sie es findet. Das elsewird nur ausgeführt, wenn nichts gefunden wird.
Alexis

Antworten:

212

(Dies ist inspiriert von der Antwort von @Mark Tolonen.)

Eine ifAnweisung führt ihre elseKlausel aus, wenn ihre Bedingung false ergibt. Identisch führt eine whileSchleife die else-Klausel aus, wenn ihre Bedingung false ergibt.

Diese Regel entspricht dem von Ihnen beschriebenen Verhalten:

  • Bei der normalen Ausführung wird die while-Schleife wiederholt ausgeführt, bis die Bedingung als falsch ausgewertet wird, und daher wird beim Verlassen der Schleife natürlich die else-Klausel ausgeführt.
  • Wenn Sie eine breakAnweisung ausführen , verlassen Sie die Schleife, ohne die Bedingung auszuwerten, sodass die Bedingung nicht als falsch ausgewertet werden kann und Sie die else-Klausel niemals ausführen.
  • Wenn Sie eine continueAnweisung ausführen , bewerten Sie die Bedingung erneut und tun genau das, was Sie normalerweise zu Beginn einer Schleifeniteration tun würden. Wenn die Bedingung wahr ist, führen Sie eine Schleife durch, aber wenn sie falsch ist, führen Sie die else-Klausel aus.
  • Andere Methoden zum Verlassen der Schleife, z. B. return, bewerten die Bedingung nicht und führen daher die else-Klausel nicht aus.

forSchleifen verhalten sich genauso. Betrachten Sie die Bedingung einfach als wahr, wenn der Iterator mehr Elemente enthält, oder andernfalls als falsch.

drawoc
quelle
8
Dies ist eine hervorragende Antwort. Behandeln Sie Ihre Schleifen wie eine Reihe von elif-Anweisungen, und das else-Verhalten enthüllt seine natürliche Logik.
Nomenator
1
Ich mag diese Antwort auch, aber sie zeichnet keine Analogie zu einer Reihe von elifAussagen. Es gibt eine Antwort , die dies tut, und es gibt eine Netto-Gegenstimme.
Alexis
2
Nun, nicht genau, eine while-Schleife könnte dazu führen, dass die Bedingung kurz vor dem Erreichen von False erfüllt wird. breakIn diesem Fall elsewürde das nicht ausgeführt, aber die Bedingung ist False. Ähnlich kann es mit forSchleifen breakauf dem letzten Element sein.
Tadhg McDonald-Jensen
36

Stellen Sie sich das besser so vor: Der elseBlock wird immer ausgeführt, wenn im vorhergehenden Block alles richtig läuft for, so dass er erschöpft ist.

Richtig in diesem Zusammenhang bedeutet nein exception, nein break, nein return. Jede Anweisung, von der aus die Kontrolle übernommen forwird, führt dazu, dass der elseBlock umgangen wird.


Ein häufiger Anwendungsfall wird bei der Suche nach einem Artikel in einem gefunden iterable, für den die Suche entweder abgebrochen wird, wenn der Artikel gefunden wird, oder eine "not found"Flagge über den folgenden elseBlock gehisst / gedruckt wird :

for items in basket:
    if isinstance(item, Egg):
        break
else:
    print("No eggs in basket")  

A continueentführt die Kontrolle nicht von for, so dass die Kontrolle elsenach dem forErschöpfen der fortgesetzt wird.

Moses Koledoye
quelle
20
Klingt sehr schön ... aber dann würden Sie erwarten, dass eine elseKlausel ausgeführt wird, wenn die Dinge nicht richtig laufen, nicht wahr? Ich bin schon wieder verwirrt ...
Alexis
Ich muss Ihnen in Bezug auf "Technisch gesehen, es ist nicht [semantisch ähnlich wie jedes andere else]" widersprechen , da das ausgeführt elsewird, wenn keine der Bedingungen in der for-Schleife als wahr ausgewertet wird, wie ich in meiner Antwort
Tadhg McDonald- Jensen
@ TadhgMcDonald-Jensen Sie können auch die Schleife auf einem brechen False. So ist die Frage, wie das forist gebrochen , hängt vom Anwendungsfall.
Moses Koledoye
Das ist richtig, ich frage nach einer Möglichkeit, irgendwie in Beziehung zu setzen, was mit der englischen Bedeutung von "else" passiert (was sich in der Tat in anderen Verwendungen von elsein Python widerspiegelt ). Sie bieten eine gute intuitive Zusammenfassung dessen else, was @Moses tut, aber nicht, wie wir dieses Verhalten mit "else" verknüpfen könnten. Wenn ein anderes Schlüsselwort verwendet würde (z. B. nobreakwie in dieser Antwort auf eine verwandte Frage erwähnt), wäre es einfacher, einen Sinn zu finden.
Alexis
1
Es hat wirklich nichts mit "Dingen, die richtig laufen" zu tun. Das else wird nur ausgeführt, wenn die Bedingung if/ als whilefalsch ausgewertet wird oder forkeine Elemente mehr vorhanden sind. breakexistiert die enthaltende Schleife (nach dem else). continuegeht zurück und wertet den Schleifenzustand erneut aus.
Mark Tolonen
31

Wann führt ein ifein else? Wenn sein Zustand falsch ist. Es ist genau das gleiche für das while/ else. Sie können sich also while/ elseals nur eine ifvorstellen, die ihren wahren Zustand so lange beibehält, bis sie als falsch ausgewertet wird. A breakändert das nicht. Es springt einfach ohne Auswertung aus der enthaltenen Schleife. Das elsewird nur ausgeführt, wenn die Auswertung der if/ whileBedingung falsch ist.

Das forist ähnlich, außer dass sein falscher Zustand seinen Iterator erschöpft.

continueund breaknicht ausführen else. Das ist nicht ihre Funktion. Das beendet breakdie enthaltende Schleife. Das continuegeht zurück zum Anfang der enthaltenden Schleife, wo die Schleifenbedingung ausgewertet wird. Es ist der Akt der Bewertung if/ whilefalsch (oder forhat keine Elemente mehr), der ausgeführt wird elseund keine andere Möglichkeit.

Mark Tolonen
quelle
1
Was Sie sagen, klingt sehr vernünftig, aber die drei Abbruchbedingungen zusammenzufassen, "bis [die Bedingung] falsch ist oder bricht / fortfährt", ist falsch: Entscheidend ist, dass die elseKlausel ausgeführt wird, wenn die Schleife mit continue(oder normalerweise) beendet wird, aber nicht wenn wir mit verlassen break. Diese Feinheiten sind der Grund, warum ich wirklich versuche zu verstehen, was elsefängt und was nicht.
Alexis
4
@alexis ja ich musste dort klären. Bearbeitet. continue führt das else nicht aus, kehrt jedoch zum Anfang der Schleife zurück, die dann möglicherweise als false ausgewertet wird.
Mark Tolonen
24

Dies ist, was es im Wesentlichen bedeutet:

for/while ...:
    if ...:
        break
if there was a break:
    pass
else:
    ...

Es ist eine schönere Art, dieses gemeinsame Muster zu schreiben:

found = False
for/while ...:
    if ...:
        found = True
        break
if not found:
    ...

Die elseKlausel wird nicht ausgeführt, wenn es ein returnweil gibt, returndas die Funktion verlässt, wie es beabsichtigt ist. Die einzige Ausnahme zu dem, an das Sie vielleicht denken finally, ist, dass sichergestellt werden soll, dass es immer ausgeführt wird.

continuehat damit nichts besonderes zu tun. Dadurch wird die aktuelle Iteration der Schleife beendet, wodurch möglicherweise die gesamte Schleife beendet wird break. In diesem Fall wurde die Schleife eindeutig nicht durch a beendet .

try/else ist ähnlich:

try:
    ...
except:
    ...
if there was an exception:
    pass
else:
    ...
Alex Hall
quelle
20

Wenn Sie sich Ihre Schleifen als eine ähnliche Struktur vorstellen (etwas Pseudocode):

loop:
if condition then

   ... //execute body
   goto loop
else
   ...

es könnte ein bisschen sinnvoller sein. Eine Schleife ist im Wesentlichen nur eine ifAnweisung, die wiederholt wird, bis die Bedingung erfüllt ist false. Und das ist der wichtige Punkt. Die Schleife überprüft ihren Zustand und stellt fest, dass dies der falseFall ist , führt also die else(genau wie eine normale if/else) aus und dann ist die Schleife fertig.

Beachten Sie also, dass der else einzige get ausgeführt wird, wenn die Bedingung überprüft wird . Das heißt, wenn Sie den Hauptteil der Schleife während der Ausführung mit beispielsweise a returnoder a verlassen break, wird der elseFall nicht ausgeführt , da die Bedingung nicht erneut überprüft wird.

A continuehingegen stoppt die aktuelle Ausführung und springt dann zurück, um den Zustand der Schleife erneut zu überprüfen, weshalb der elsein diesem Szenario erreicht werden kann.

Keiwan
quelle
Diese Antwort gefällt mir ziemlich gut, aber Sie können sie vereinfachen: Lassen Sie das endEtikett weg und stecken Sie es einfach goto loopin den ifKörper. Vielleicht sogar übertroffen, indem man das ifin die gleiche Zeile wie das Etikett setzt, und es sieht plötzlich sehr nach dem Original aus.
Bergi
@Bergi Ja, ich denke das macht es ein bisschen klarer, danke.
Keiwan
15

Mein Gotcha-Moment mit der elseKlausel der Schleife war, als ich einen Vortrag von Raymond Hettinger sah , der eine Geschichte darüber erzählte, wie er dachte, dass er hätte heißen sollen nobreak. Schauen Sie sich den folgenden Code an. Was würde er Ihrer Meinung nach tun?

for i in range(10):
    if test(i):
        break
    # ... work with i
nobreak:
    print('Loop completed')

Was würden Sie vermuten, dass es tut? Nun, der Teil, der sagt, nobreakwürde nur ausgeführt, wenn eine breakAnweisung nicht in der Schleife getroffen würde.

nasser-sh
quelle
8

Normalerweise denke ich an eine Schleifenstruktur wie diese:

for item in my_sequence:
    if logic(item):
        do_something(item)
        break

Um einer variablen Anzahl von if/elifAnweisungen sehr ähnlich zu sein :

if logic(my_seq[0]):
    do_something(my_seq[0])
elif logic(my_seq[1]):
    do_something(my_seq[1])
elif logic(my_seq[2]):
    do_something(my_seq[2])
....
elif logic(my_seq[-1]):
    do_something(my_seq[-1])

In diesem Fall elsefunktioniert die Anweisung in der for-Schleife genau wie die elseAnweisung in der Kette von elifs. Sie wird nur ausgeführt, wenn keine der Bedingungen zuvor als True ausgewertet wurde. (oder Unterbrechung der Ausführung mit returnoder mit einer Ausnahme) Wenn meine Schleife normalerweise nicht dieser Spezifikation entspricht, verzichte ich aus for: elsegenau dem Grund, aus dem Sie diese Frage gestellt haben, auf die Verwendung: Sie ist nicht intuitiv.

Tadhg McDonald-Jensen
quelle
Richtig. Eine Schleife wird jedoch mehrmals ausgeführt, sodass ein wenig unklar ist, wie Sie dies auf eine for-Schleife anwenden möchten. Könntest Du das erläutern?
Alexis
@alexis Ich habe meine Antwort überarbeitet, ich denke, es ist jetzt viel klarer.
Tadhg McDonald-Jensen
7

Andere haben bereits die Mechanik von erklärt while/for...else, und die Python 3-Sprachreferenz hat die maßgebliche Definition (siehe while und for ), aber hier ist meine persönliche Mnemonik, FWIW. Ich denke, der Schlüssel für mich war, dies in zwei Teile zu unterteilen: einen zum Verständnis der Bedeutung der elsein Bezug auf die Schleifenbedingung und einen zum Verständnis der Schleifensteuerung.

Ich finde es am einfachsten, zunächst zu verstehen while...else:

whileSie haben mehr Gegenstände, tun Sachen, elsewenn Sie ausgehen, tun Sie dies

Die for...elseMnemonik ist im Grunde die gleiche:

forjeden Gegenstand, mach Sachen, aber elsewenn du keinen mehr hast, mach das

In beiden Fällen wird das elseTeil erst erreicht, wenn keine weiteren Elemente mehr zu verarbeiten sind und das letzte Element regelmäßig verarbeitet wurde (dh nein breakoder return). A continuegeht einfach zurück und sieht nach, ob es noch weitere Gegenstände gibt. Meine Mnemonik für diese Regeln gilt für beide whileund for:

Wenn es geht breakoder geht return, gibt es nichts elsezu tun,
und wenn ich sage continue, ist das für Sie "Loop Back to Start"

- mit „Schleife zurück zum Anfang“ , das heißt, natürlich, der Anfang der Schleife , wo wir prüfen , ob es noch weitere Elemente in der iterable sind, so weit das elsegeht, continuespielt wirklich keine Rolle überhaupt.

Fabian Fagerholm
quelle
4
Ich würde vorschlagen, dass es verbessert werden könnte, indem gesagt wird, dass der übliche Zweck einer for / else-Schleife darin besteht, Elemente zu untersuchen, bis Sie gefunden haben, wonach Sie suchen und aufhören möchten , oder wenn Ihnen die Elemente ausgehen. Das "else" ist vorhanden, um den Teil "Ihnen gehen die Elemente aus (ohne gefunden zu haben, wonach Sie gesucht haben)" zu behandeln.
Supercat
@supercat: Könnte sein, aber ich weiß nicht, was die häufigsten Verwendungen da draußen sind. Das elsekönnte auch verwendet werden, um etwas zu tun, wenn Sie einfach mit allen Gegenständen fertig sind. Beispiele hierfür sind das Schreiben eines Protokolleintrags, das Aktualisieren einer Benutzeroberfläche oder das Signalisieren eines anderen Prozesses, dass Sie fertig sind. Eigentlich alles. Außerdem haben einige Codeteile das "erfolgreiche" Fallende mit einem " breakinnerhalb der Schleife", und das elsewird verwendet, um den "Fehler" -Fall zu behandeln, bei dem Sie während der Iteration kein geeignetes Element gefunden haben (vielleicht haben Sie das gedacht von?).
Fabian Fagerholm
1
Der Fall, an den ich dachte, war genau der Fall, in dem der erfolgreiche Fall mit einer "Pause" endet und das "Sonst" einen Mangel an Erfolg behandelt. Wenn es innerhalb einer Schleife keine "Unterbrechung" gibt, kann der "else" -Code genauso gut der Schleife als Teil des umschließenden Blocks folgen.
Supercat
Es sei denn, Sie müssen zwischen dem Fall unterscheiden, in dem die Schleife alle iterierbaren Elemente ohne Unterbrechung durchlaufen hat (und das war ein erfolgreicher Fall), und dem Fall, in dem dies nicht der Fall war. Dann müssen Sie den "finalisierenden" Code in den elseBlock der Schleife einfügen oder das Ergebnis auf andere Weise verfolgen. Grundsätzlich stimme ich zu, ich sage nur, dass ich nicht weiß, wie Benutzer diese Funktion verwenden, und daher möchte ich vermeiden, Annahmen darüber zu treffen, ob das elseSzenario " Behandelt einen erfolgreichen Fall" oder das Szenario " elseBehandelt einen nicht erfolgreichen Fall" häufiger vorkommt. Aber Sie haben einen guten Punkt, also Kommentar positiv bewertet!
Fabian Fagerholm
7

In der testgetriebenen Entwicklung (TDD) behandeln Sie Schleifen bei Verwendung des Paradigmas der Transformationsprioritätsprämisse als Verallgemeinerung von bedingten Anweisungen.

Dieser Ansatz lässt sich gut mit dieser Syntax kombinieren, wenn Sie nur einfache if/else(keine elif) Anweisungen berücksichtigen :

if cond:
    # 1
else:
    # 2

verallgemeinert auf:

while cond:  # <-- generalization
    # 1
else:
    # 2

schön.

In anderen Sprachen erfordern TDD-Schritte von einem Einzelfall zu Fällen mit Sammlungen mehr Refactoring.


Hier ist ein Beispiel aus dem 8thlight-Blog :

In dem verlinkten Artikel im 8thlight-Blog wird die Word Wrap-Kata berücksichtigt: Hinzufügen von Zeilenumbrüchen zu Zeichenfolgen (die sVariable in den folgenden Snippets), damit sie auf eine bestimmte Breite passen (die lengthVariable in den folgenden Snippets). An einem Punkt sieht die Implementierung wie folgt aus (Java):

String result = "";
if (s.length() > length) {
    result = s.substring(0, length) + "\n" + s.substring(length);
} else {
    result = s;
}
return result;

und der nächste Test, der derzeit fehlschlägt, ist:

@Test
public void WordLongerThanTwiceLengthShouldBreakTwice() throws Exception {
    assertThat(wrap("verylongword", 4), is("very\nlong\nword"));
    }

Wir haben also Code, der bedingt funktioniert: Wenn eine bestimmte Bedingung erfüllt ist, wird ein Zeilenumbruch hinzugefügt. Wir möchten den Code verbessern, um mehrere Zeilenumbrüche zu verarbeiten. Die im Artikel vorgestellte Lösung schlägt vor, die Transformation (if-> while) anzuwenden. Der Autor gibt jedoch einen Kommentar ab, der Folgendes enthält :

Während Schleifen keine elseKlauseln haben können, müssen wir den elsePfad entfernen, indem wir weniger im ifPfad tun . Auch dies ist ein Refactoring.

Dies zwingt dazu, im Rahmen eines fehlgeschlagenen Tests weitere Änderungen am Code vorzunehmen:

String result = "";
while (s.length() > length) {
    result += s.substring(0, length) + "\n";
    s = s.substring(length);
}
result += s;

In TDD möchten wir so wenig Code wie möglich schreiben, damit die Tests bestanden werden. Dank der Python-Syntax ist folgende Transformation möglich:

von:

result = ""
if len(s) > length:
    result = s[0:length] + "\n"
    s = s[length:]
else:
    result += s

zu:

result = ""
while len(s) > length:
    result += s[0:length] + "\n"
    s = s[length:]
else:
    result += s
BartoszKP
quelle
6

So wie ich es sehe, else:wird ausgelöst , wenn Sie über das Ende der Schleife hinaus iterieren.

Wenn Sie breakoder returnoder raiseSie nicht über das Ende der Schleife hinaus iterieren, stoppen Sie sofort und der else:Block wird daher nicht ausgeführt. Wenn Sie continueimmer noch über das Ende der Schleife iterieren, springen Sie einfach mit der nächsten Iteration fort. Es stoppt die Schleife nicht.

Winston Ewert
quelle
1
Ich mag das, ich denke du bist auf etwas. Es hängt ein wenig damit zusammen, wie Looping in den schlechten alten Zeiten vor Loop-Schlüsselwörtern implementiert wurde. (Nämlich: Der Scheck wurde am Ende der Schleife platziert, wobei gotoder Erfolg oben steht.) Aber es ist eine kürzere Version der Antwort mit der höchsten Abstimmung ...
alexis
@alexis, subjektiv, aber ich finde es einfacher, darüber nachzudenken.
Winston Ewert
eigentlich stimme ich zu. Wenn auch nur, weil es prägnanter ist.
Alexis
4

Stellen Sie sich die elseKlausel als Teil des Schleifenkonstrukts vor. breakbricht vollständig aus dem Schleifenkonstrukt aus und überspringt somit die elseKlausel.

Aber wirklich, meine mentale Zuordnung ist einfach, dass es die 'strukturierte' Version des Musters C / C ++ ist:

  for (...) {
    ...
    if (test) { goto done; }
    ...
  }
  ...
done:
  ...

Wenn ich for...elsees also selbst begegne oder schreibe, anstatt es direkt zu verstehen , übersetze ich es mental in das obige Verständnis des Musters und erarbeite dann, welche Teile der Python-Syntax welchen Teilen des Musters zugeordnet sind.

(Ich setze 'strukturiert' in Angstzitate, weil der Unterschied nicht darin besteht, ob der Code strukturiert oder unstrukturiert ist, sondern lediglich darin, ob der jeweiligen Struktur Schlüsselwörter und Grammatik zugeordnet sind.)


quelle
1
Wo ist das else? Wenn Sie meinten, das done:Etikett soll Proxy stehen oder else:ich glaube, Sie haben es genau rückwärts.
Alexis
@alexis Der 'else'-Code würde das' ... ' unmittelbar vor dem done:Etikett ausfüllen . Die Gesamtkorrespondenz lässt sich vielleicht am besten so sagen: Python hat das elseKonstrukt -on-loop, mit dem Sie dieses Kontrollflussmuster ohne ausdrücken können goto.
zwol
Es gibt andere Möglichkeiten, dieses Kontrollflussmuster auszuführen, z. B. durch Setzen eines Flags. Das elsevermeidet das.
Alexis
2

Wenn Sie paaren elsemit for, könnte es verwirrend sein. Ich denke nicht, dass das Schlüsselwort elseeine gute Wahl für diese Syntax war, aber wenn Sie elsemit ifdem enthaltenen breakkombinieren, können Sie sehen, dass es tatsächlich Sinn macht. elseist kaum nützlich, wenn es keine vorhergehende ifAussage gibt, und ich glaube, deshalb hat der Syntaxdesigner das Schlüsselwort gewählt.

Lassen Sie es mich in menschlicher Sprache demonstrieren.

forJede Person in einer Gruppe von Verdächtigen ifist der Verbrecher breakder Ermittlungen. elseFehler melden.

Bomben
quelle
1

Die Art und Weise, wie ich darüber denke, ist der Schlüssel, continueeher die Bedeutung von als zu berücksichtigen else.

Die anderen Schlüsselwörter, die Sie erwähnen, brechen aus der Schleife aus (beenden ungewöhnlich), während continuedies nicht der Fall ist. Sie überspringen lediglich den Rest des Codeblocks innerhalb der Schleife. Die Tatsache, dass es der Schleifenbeendigung vorausgehen kann, ist zufällig: Die Beendigung erfolgt tatsächlich auf normale Weise durch Auswertung des bedingten Schleifenausdrucks.

Dann müssen Sie nur noch daran denken, dass die elseKlausel nach der normalen Schleifenbeendigung ausgeführt wird.

Bob Sammers
quelle
0
# tested in Python 3.6.4
def buy_fruit(fruits):
    '''I translate the 'else' below into 'if no break' from for loop '''
    for fruit in fruits:
        if 'rotten' in fruit:
            print(f'do not want to buy {fruit}')
            break
    else:  #if no break
        print(f'ready to buy {fruits}')


if __name__ == '__main__':
    a_bag_of_apples = ['golden delicious', 'honeycrisp', 'rotten mcintosh']
    b_bag_of_apples = ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
    buy_fruit(a_bag_of_apples)
    buy_fruit(b_bag_of_apples)

'''
do not want to buy rotten mcintosh
ready to buy ['granny smith', 'red delicious', 'honeycrisp', 'gala', 'fuji']
'''
Den Bach runter
quelle