Ich verstehe, wie dieses Konstrukt funktioniert:
for i in range(10):
print(i)
if i == 9:
print("Too big - I'm giving up!")
break;
else:
print("Completed successfully")
Aber ich verstehe nicht, warum else
hier als Schlüsselwort verwendet wird, da dies darauf hindeutet, dass der betreffende Code nur ausgeführt wird, wenn der for
Block nicht vollständig ist, was das Gegenteil von dem ist, was er tut! Egal wie ich darüber denke, mein Gehirn kann nicht nahtlos von der for
Aussage zum else
Block übergehen. Für mich continue
oder continuewith
würde mehr Sinn machen (und ich versuche mich zu trainieren, es als solches zu lesen).
Ich frage mich, wie Python-Codierer dieses Konstrukt in ihrem Kopf lesen (oder laut, wenn Sie möchten). Vielleicht fehlt mir etwas, das solche Codeblöcke leichter entzifferbar macht?
python
if-statement
for-loop
for-else
Kent Boogaart
quelle
quelle
break
es in "Ich habe es gefunden" -Schleifen häufig verwendet wird, können Sie es in "Wenn nicht gefunden" übersetzen , was nicht weit von dem entfernt ist, waselse
lautetfor ... else foo()
und nurfoo()
nach der for-Schleife setzen?" Und die Antwort ist, dass sie sich nur dann anders verhalten, wenn die Schleife ein enthältbreak
(wie unten ausführlich beschrieben).Antworten:
Es ist ein seltsames Konstrukt, selbst für erfahrene Python-Codierer. In Verbindung mit for-Schleifen bedeutet dies im Grunde "Finde ein Element in der Iterable, sonst, wenn keines gefunden wurde, mache ...". Wie in:
Immer wenn Sie dieses Konstrukt sehen, ist es eine bessere Alternative, die Suche entweder in eine Funktion zu kapseln:
Oder verwenden Sie ein Listenverständnis:
Es ist nicht semantisch äquivalent zu den beiden anderen Versionen, funktioniert jedoch in nicht leistungskritischem Code, bei dem es keine Rolle spielt, ob Sie die gesamte Liste durchlaufen oder nicht, gut genug. Andere mögen anderer Meinung sein, aber ich persönlich würde es vermeiden, jemals die for-else- oder while-else-Blöcke im Produktionscode zu verwenden.
Siehe auch [Python-Ideen] Zusammenfassung von für ... sonstige Threads
quelle
for
Schleifenbeispielen nach einem einzelnen Element suchen und einen Generatorausdruck / ein Listenverständnis verwenden möchten, möchtennext((o for o in objects if o.key == search_key), None)
oder wickeln Sie es in eintry
/except
und verwenden keinen Standardwert anstelle einesif
/else
.for/else
Konstrukt zu verwenden.else
mit einer gepaart wurde,for
und ich hatte keine Ahnung, dass dies legal war.break
Anweisung wird explizit wie in diesem Beispiel ausgeführt. Aus den obigen Dokumenten: "Dieelse
Klausel hat ein anderes wahrgenommenes Problem: Wenn sich keinebreak
in der Schleife befindet, ist dieelse
Klausel funktional redundant." zBfor x in [1, 2, 3]:\n print x\n else:\n print 'this executes due to no break'
Ein übliches Konstrukt besteht darin, eine Schleife auszuführen, bis etwas gefunden ist, und dann aus der Schleife auszubrechen. Das Problem ist, dass ich feststellen muss, welcher Fall passiert ist, wenn ich aus der Schleife ausbreche oder die Schleife endet. Eine Methode besteht darin, ein Flag oder eine Speichervariable zu erstellen, mit der ich einen zweiten Test durchführen kann, um festzustellen, wie die Schleife beendet wurde.
Angenommen, ich muss eine Liste durchsuchen und jedes Element verarbeiten, bis ein Flag-Element gefunden wird, und dann die Verarbeitung beenden. Wenn das Flag-Element fehlt, muss eine Ausnahme ausgelöst werden.
Verwenden Sie das Python
for
...else
-Konstrukt, das Sie habenVergleichen Sie dies mit einer Methode, die diesen syntaktischen Zucker nicht verwendet:
Im ersten Fall
raise
ist das eng an die for-Schleife gebunden, mit der es arbeitet. Im zweiten Fall ist die Bindung nicht so stark und es können Fehler während der Wartung auftreten.quelle
Python: the good parts
Buch machen.process(i)
dies für jeden Artikelmylist
genau vorhertheflag
und nicht für sichtheflag
selbst geschieht ? Ist es das, was beabsichtigt war?process
wird für jedes Element ausgeführti
, das in der Liste vorhandentheflag
ist, bevor es erreicht wurde. Es wird nicht für Elemente in der Liste ausgeführt, nachdem es erreicht wurdetheflag
, und es wird nicht für ausgeführttheflag
.Es gibt eine ausgezeichnete Präsentation von Raymond Hettinger mit dem Titel Transforming Code in Beautiful, Idiomatic Python , in der er kurz auf die Geschichte des
for ... else
Konstrukts eingeht . Der relevante Abschnitt ist "Unterscheiden mehrerer Austrittspunkte in Schleifen" ab 15:50 Uhr und dauert etwa drei Minuten. Hier sind die Höhepunkte:for ... else
Konstrukt wurde von Donald Knuth als Ersatz für bestimmteGOTO
Anwendungsfälle entwickelt;else
Schlüsselworts machte Sinn, weil "es das ist, was Knuth benutzte, und die Leute wussten zu dieser Zeit, dass alle [for
Aussagen] einif
undGOTO
darunter eingebettet hatten , und sie erwarteten daselse
;"Wenn die Frage lautet: "Warum ändern sie dieses Schlüsselwort nicht?" dann gab Cat Plus Plus wahrscheinlich die genaueste Antwort - zu diesem Zeitpunkt wäre es zu destruktiv für vorhandenen Code, um praktisch zu sein. Aber wenn die Frage, die Sie wirklich stellen, ist, warum sie überhaupt
else
wiederverwendet wurde, dann schien es zu dieser Zeit anscheinend eine gute Idee zu sein.Persönlich mag ich den Kompromiss, inline zu kommentieren
# no break
, wo immerelse
dies auf einen Blick als innerhalb der Schleife liegend verwechselt werden könnte. Es ist ziemlich klar und prägnant. Diese Option wird in der Zusammenfassung, die Björn am Ende seiner Antwort verlinkt hat, kurz erwähnt :* Bonuszitat aus diesem Teil des Videos: "Genau wie wenn wir Lambda Makefunction nennen würden, würde niemand fragen: 'Was macht Lambda?'"
quelle
Weil sie kein neues Schlüsselwort in die Sprache einführen wollten. Jeder stiehlt eine Kennung und verursacht Abwärtskompatibilitätsprobleme. Daher ist dies normalerweise ein letzter Ausweg.
quelle
finally
in diesem Fall eine bessere Wahl gewesen zu sein. War das Schlüsselwort finally zum Zeitpunkt der Einführung dieses Konstrukts noch nicht vorhanden?finally
ist nicht viel besser, da dies impliziert, dass der Block immer nach der Schleife ausgeführt wird, und dies ist auch nicht der Fall (da dies überflüssig wäre, wenn nur der Code nach der Schleife ausgeführt würde).finally
dass die else-Klausel auch ausgeführt wird, wenncontinue
sie in der for-Schleife verwendet wird - das ist möglicherweise viele Male und nicht nur am Ende.else
Klausel Ausführung wird nicht von betroffencontinue
( docs und Testcode )else
wird nur ausgeführt, wenncontinue
es das für die letzte Iteration war.Um es einfach zu machen, können Sie sich das so vorstellen.
break
Befehl in derfor
Schleife stößt , wird daselse
Teil nicht aufgerufen.break
Befehl in derfor
Schleife nicht auftritt, wird daselse
Teil aufgerufen.Mit anderen Worten, wenn für die Schleifeniteration nicht mit "gebrochen" wird
break
, wird derelse
Teil aufgerufen.quelle
else
Block wird auch nicht ausgeführt, wenn der Hauptteil der Schleife eine Ausnahme auslöst.Der einfachste Weg, um herauszufinden, was das for / else getan hat, und was noch wichtiger ist, wann ich es verwenden soll, war mich darauf zu konzentrieren, wohin die break-Anweisung springt. Das For / else-Konstrukt ist ein einzelner Block. Die Pause springt aus dem Block und springt so über die else-Klausel. Wenn der Inhalt der else-Klausel einfach der for-Klausel folgt, wird sie niemals übersprungen, und daher müsste die entsprechende Logik bereitgestellt werden, indem sie in ein if eingefügt wird. Dies wurde bereits gesagt, aber nicht ganz in diesen Worten, so dass es jemand anderem helfen kann. Versuchen Sie, das folgende Codefragment auszuführen. Ich bin aus Gründen der Klarheit von ganzem Herzen für den Kommentar "Keine Pause".
quelle
for:
/ zu "bekommen"else:
, liefert es keine wirkliche Rechtfertigung für das Schlüsselwort Wesenelse
. Angesichts der hier gegebenen Rahmungthen:
scheint es viel natürlicher zu sein. (Es gibt Gründe fürelse
die Auswahl, die in anderen Antworten angegeben sind - sie werden hier einfach nicht angegeben.)Ich denke, die Dokumentation hat eine großartige Erklärung für andere , fahren Sie fort
Quelle: Python 2 docs: Tutorial zum Kontrollfluss
quelle
Ich habe es so gelesen wie:
Wenn Sie immer noch die Voraussetzungen haben, um die Schleife auszuführen, tun Sie etwas , sonst etwas anderes.
quelle
for:
/else:
lässt es so klingen, als würde derelse:
Wille immer nach der Schleife laufen, was nicht der Fall ist.Da der technische Teil ziemlich genau beantwortet wurde, bezieht sich mein Kommentar nur auf die Verwirrung , die dieses recycelte Schlüsselwort erzeugt.
Da Python eine sehr beredte Programmiersprache ist, ist der Missbrauch eines Schlüsselworts berüchtigter. Das
else
Schlüsselwort beschreibt perfekt einen Teil des Ablaufs eines Entscheidungsbaums: "Wenn Sie dies nicht können, tun Sie das (sonst)". Es ist in unserer eigenen Sprache impliziert .Stattdessen führt die Verwendung dieses Schlüsselworts mit
while
undfor
-Anweisungen zu Verwirrung. Der Grund, unsere Karriere als Programmierer hat uns gelehrt, dass dieelse
Aussage in einem Entscheidungsbaum liegt; sein logischer Bereich , ein Wrapper, der bedingt einen Pfad zurückgibt, dem er folgen soll. In der Zwischenzeit haben Schleifenanweisungen ein bildliches explizites Ziel, etwas zu erreichen. Das Ziel wird nach kontinuierlichen Iterationen eines Prozesses erreicht.if / else
Geben Sie einen Pfad an, dem Sie folgen möchten . Schleifen folgen einem Pfad, bis das "Ziel" erreicht ist .Das Problem ist, dass dies
else
ein Wort ist, das die letzte Option in einer Bedingung klar definiert. Die Semantik des Wortes sind beide geteilt durch Python und menschliche Sprache. Das Wort else in der menschlichen Sprache wird jedoch niemals verwendet, um die Aktionen anzugeben, die jemand oder etwas ausführen wird, nachdem etwas abgeschlossen ist. Es wird verwendet, wenn während des Abschlusses ein Problem auftritt (eher wie eine break- Anweisung).Am Ende bleibt das Schlüsselwort in Python. Es ist klar, dass es ein Fehler war, klarer, wenn jeder Programmierer versucht, eine Geschichte zu entwickeln, um seine Verwendung wie ein Gedächtnisgerät zu verstehen. Ich hätte es geliebt, wenn sie stattdessen das Schlüsselwort gewählt hätten
then
. Ich glaube, dass dieses Schlüsselwort perfekt in diesen iterativen Ablauf passt, die Auszahlung nach der Schleife.Es ähnelt der Situation, die ein Kind hat, nachdem es jeden Schritt beim Zusammenbau eines Spielzeugs befolgt hat : Und DANN welcher Vater?
quelle
Ich las es wie
iterable
folgt: "Wenn das vollständig erschöpft ist und die Ausführung nach Abschluss des Vorgangs mit der nächsten Anweisung fortfährtfor
, wird die else-Klausel ausgeführt." Wenn also die Iteration unterbrochen wirdbreak
, wird dies nicht ausgeführt.quelle
Ich stimme zu, es ist eher wie ein "Elif nicht [Bedingung (en), die eine Pause einlegen]".
Ich weiß, dass dies ein alter Thread ist, aber ich beschäftige mich gerade mit derselben Frage, und ich bin nicht sicher, ob jemand die Antwort auf diese Frage so erfasst hat, wie ich sie verstehe.
Für mich gibt es drei Möglichkeiten, das
else
InFor... else
oder dieWhile... else
Anweisungen zu "lesen" , die alle gleichwertig sind:else
==
if the loop completes normally (without a break or error)
else
==
if the loop does not encounter a break
else
==
else not (condition raising break)
(Vermutlich gibt es eine solche Bedingung, oder Sie hätten keine Schleife)Im Wesentlichen ist das "else" in einer Schleife also wirklich ein "elif ...", wobei "..." (1) keine Unterbrechung ist, was (2) NICHT [Bedingung (en), die eine Unterbrechung auslösen] entspricht.
Ich denke, der Schlüssel ist, dass das
else
ohne die 'Pause' sinnlos ist, alsofor...else
beinhaltet a:Die wesentlichen Elemente einer
for...else
Schleife lauten also wie folgt, und Sie würden sie in einfacherem Englisch lesen als:Wie auf den anderen Postern bereits erwähnt, wird in der Regel eine Unterbrechung ausgelöst, wenn Sie feststellen können, wonach Ihre Schleife sucht. Dies
else:
wird zu "Was tun, wenn das Zielobjekt nicht gefunden wird".Beispiel
Sie können auch Ausnahmebehandlung, Unterbrechungen und for-Schleifen zusammen verwenden.
Ergebnis
Beispiel
Einfaches Beispiel mit einer Pause.
Ergebnis
Beispiel
Einfaches Beispiel, bei dem keine Unterbrechung, keine Bedingung, die eine Unterbrechung auslöst, und kein Fehler auftreten.
Ergebnis
quelle
Das
else
Schlüsselwort kann hier verwirrend sein, und so viele Menschen darauf hingewiesen haben, so etwas wienobreak
,notbreak
ist besser geeignet.Um zu verstehen ,
for ... else ...
logisch, vergleichen sie mittry...except...else
, nichtif...else...
, die meisten Python - Programmierer mit dem folgenden Code vertraut sind:Stellen Sie sich das
break
als eine besondere Art von vorException
:Der Unterschied ist
python
impliziertexcept break
und Sie können es nicht ausschreiben, so wird es:Ja, ich weiß, dass dieser Vergleich schwierig und lästig sein kann, aber er verdeutlicht die Verwirrung.
quelle
Codes im
else
Anweisungsblock werden ausgeführt, wenn diefor
Schleife nicht unterbrochen wurde.Aus den Dokumenten: break and continue-Anweisungen und sonst Klauseln für Schleifen
quelle
Hier ist eine Möglichkeit, darüber nachzudenken, die ich oben noch nicht erwähnt habe:
Denken Sie zunächst daran, dass for-Schleifen im Grunde nur syntaktischer Zucker um while-Schleifen sind. Zum Beispiel die Schleife
kann (ungefähr) umgeschrieben werden als
Zweitens, denken Sie daran, dass while-Schleifen im Grunde nur if-Blöcke wiederholt werden! Sie können eine while-Schleife immer als "Wenn diese Bedingung erfüllt ist, führen Sie den Body aus und kehren Sie dann zurück und überprüfen Sie erneut".
Also, während / else vollkommen Sinn macht: Es ist genau die gleiche Struktur wie wenn / else, mit der zusätzlichen Funktionalität der Schleife, bis die Bedingung falsch wird, anstatt die Bedingung nur einmal zu überprüfen.
Und dann macht for / else auch vollkommen Sinn: Da alle for-Schleifen nur syntaktischer Zucker über while-Schleifen sind, müssen Sie nur herausfinden, was die implizite Bedingung der zugrunde liegenden while-Schleife ist, und dann entspricht das else dem Zeitpunkt Bedingung wird falsch.
quelle
Gute Antworten sind:
Meine Anmerkung hier stammt von dem, was Donald Knuth einmal gesagt hat (Entschuldigung, ich kann keinen Hinweis finden), dass es ein Konstrukt gibt, bei dem while-else nicht von if-else zu unterscheiden ist, nämlich (in Python):
hat den gleichen Durchfluss (ohne geringe Füllstandsunterschiede) wie:
Der Punkt ist, dass if-else als syntaktischer Zucker für while-else betrachtet werden kann, was
break
am Ende seinesif
Blocks impliziert ist . Die entgegengesetzte Implikation, auf die diesewhile
Schleife erweitert wirdif
, ist häufiger (es handelt sich lediglich um eine wiederholte / geloopte bedingte Prüfung), da sieif
häufig zuvor gelehrt wirdwhile
. Dies ist jedoch nicht wahr, da dies bedeuten würde, dasselse
block-while-else jedes Mal ausgeführt wird, wenn die Bedingung falsch ist.Um Ihr Verständnis zu erleichtern, denken Sie so:
Noch ein Hinweis:
quelle
Man könnte es sich so vorstellen,
else
wie im Rest der Sachen oder den anderen Sachen, die nicht in der Schleife gemacht wurden.quelle
"else" hier ist verrückt einfach, nur gemein
1, "wenn
for clause
abgeschlossen ist"Es ist üblich, so lange Anweisungen wie "for-Klausel ist abgeschlossen" zu schreiben, damit sie "else" einführen.
else
Hier ist ein Wenn in seiner Natur.2, aber wie wäre es
for clause is not run at all
Die Aussage ist also eine logische Kombination:
oder sagen Sie es so:
oder so:
quelle
Hier ist neben der Suche ein weiterer idiomatischer Anwendungsfall. Angenommen, Sie möchten warten, bis eine Bedingung erfüllt ist, z. B. ein Port, der auf einem Remote-Server geöffnet ist, sowie eine Zeitüberschreitung. Dann könnten Sie ein
while...else
Konstrukt wie folgt verwenden:quelle
Ich habe nur versucht, es selbst wieder zu verstehen. Ich fand, dass das Folgende hilft!
• Stellen Sie sich das
else
als mit demif
Inneren der Schleife gepaart vor (anstatt mit demfor
) - wenn die Bedingung erfüllt ist, brechen Sie die Schleife, sonst tun Sie dies - außer es ist eines, daselse
mit mehrerenif
s gepaart ist !• Wenn überhaupt keine
if
s zufrieden waren, machen Sie daselse
.• Die multiplen
if
s können auch tatsächlich alsif
-elif
s betrachtet werden!quelle
Ich halte die Struktur wie für (falls) Ein anderes B, und für (if) -else ist eine besondere if-else , grob . Es kann hilfreich sein, etwas anderes zu verstehen .
A und B werden höchstens einmal ausgeführt, was der if-else-Struktur entspricht.
for (if) kann als spezielles if betrachtet werden, das eine Schleife ausführt, um zu versuchen, die if-Bedingung zu erfüllen. Sobald die if- Bedingung erfüllt ist, A und break ; Sonst B.
quelle
Python verwendet eine else after for- und while-Schleife, sodass etwas anderes passiert, wenn für die Schleife nichts gilt. Zum Beispiel:
Die Ausgabe wäre immer wieder 'Hi' (wenn ich richtig bin).
quelle