Angesichts des folgenden Codes (der nicht funktioniert):
while True:
#snip: print out current state
while True:
ok = get_input("Is this ok? (y/n)")
if ok.lower() == "y": break 2 #this doesn't work :(
if ok.lower() == "n": break
#do more processing with menus and stuff
Gibt es eine Möglichkeit, diese Arbeit zu machen? Oder muss ich eine Prüfung durchführen, um aus der Eingangsschleife auszubrechen, und eine andere, eingeschränktere Prüfung in der äußeren Schleife, um alle zusammen auszubrechen, wenn der Benutzer zufrieden ist?
python
nested-loops
break
control-flow
Matthew Scharley
quelle
quelle
goto
wenn Sie tief in viele Schleifen eingebettet sindAntworten:
Mein erster Instinkt wäre, die verschachtelte Schleife in eine Funktion umzuwandeln und
return
zum Ausbrechen zu verwenden.quelle
return
der richtige Ansatz ist. Und die Argumentation ist, dass nach dem Zen von Python "flach besser ist als verschachtelt". Wir haben hier drei Verschachtelungsebenen, und wenn dies in die Quere kommt, ist es an der Zeit, die Verschachtelung zu reduzieren oder zumindest die gesamte Verschachtelung in eine eigene Funktion zu extrahieren.Hier ist ein weiterer Ansatz, der kurz ist. Der Nachteil ist, dass Sie nur die äußere Schleife brechen können, aber manchmal ist es genau das, was Sie wollen.
Dies verwendet das for / else-Konstrukt, das unter erklärt wird: Warum verwendet Python 'else' nach for- und while-Schleifen?
Schlüsselerkenntnis: Es scheint nur so, als ob die äußere Schleife immer bricht. Aber wenn die innere Schleife nicht bricht, wird auch die äußere Schleife nicht brechen.
Die
continue
Aussage ist die Magie hier. Es steht in der For-else-Klausel. Per Definition passiert das, wenn es keine innere Unterbrechung gibt. In dieser Situation wirdcontinue
der äußere Bruch sauber umgangen.quelle
PEP 3136 schlägt die Bezeichnung break / continue vor. Guido lehnte es ab, weil "Code, der so kompliziert ist, dass er diese Funktion benötigt, sehr selten ist". Das PEP erwähnt jedoch einige Problemumgehungen (wie die Ausnahmetechnik), während Guido der Ansicht ist, dass die Umgestaltung zur Verwendung der Rückgabe in den meisten Fällen einfacher sein wird.
quelle
return
normalerweise der richtige Weg ist, habe ich einige Fälle gesehen, in denen eine einfache, prägnantebreak 2
Aussage einfach so viel Sinn machen würde. Auch Refactor /return
funktioniert nicht gleich fürcontinue
. In diesen Fällen ist das numerische Unterbrechen und Fortfahren einfacher zu verfolgen und weniger überladen als das Umgestalten einer winzigen Funktion, das Auslösen von Ausnahmen oder die verschlungene Logik, bei der ein Flag gesetzt wird, um auf jeder Verschachtelebene zu unterbrechen. Es ist eine Schande, dass Guido es abgelehnt hat.break; break
wäre nett.break
die Schleifen manuell durch alle Schleifen weiterleiten müssen . Blöd.Erstens ist gewöhnliche Logik hilfreich.
Wenn die Kündigungsbedingungen aus irgendeinem Grund nicht geklärt werden können, handelt es sich bei Ausnahmen um einen Fallback-Plan.
Für dieses spezielle Beispiel ist möglicherweise keine Ausnahme erforderlich.
Andererseits haben wir in Zeichenmodusanwendungen häufig die Optionen "Y", "N" und "Q". Für die Option "Q" möchten wir einen sofortigen Ausstieg. Das ist außergewöhnlicher.
quelle
done
). (2) Auslösen einer Ausnahme. Durch das Zusammenführen zu einer einzigen Lösung sieht es nur kompliziert aus. Für zukünftige Leser: Verwenden Sie entweder alle Zeilen, die betreffendone
, ODER definierenGetOutOfLoop(Exception)
und erhöhen / außer dem.Exception
Konstruktor (z. B.raise Exception('bla bla bla')
) sind sowohl in Python 2 als auch in Python 3 gültig. Ersteres ist in diesem Fall vorzuziehen, da wir dies nicht möchten Unserexcept
Block zum Abfangen aller Ausnahmen, aber nur der speziellen Ausnahme, mit der wir die Schleife verlassen. Wenn wir die Dinge so tun, wie Sie es vorschlagen, und dann ein Fehler in unserem Code dazu führt, dass eine unerwartete Ausnahme ausgelöst wird, wird dies fälschlicherweise genauso behandelt wie das absichtliche Verlassen der Schleife.Ich stimme eher zu, dass das Refactoring in eine Funktion normalerweise der beste Ansatz für diese Art von Situation ist. Wenn Sie jedoch wirklich aus verschachtelten Schleifen ausbrechen müssen, finden Sie hier eine interessante Variante des von @ S.Lott beschriebenen Ansatzes zum Auslösen von Ausnahmen. Es verwendet Pythons
with
Anweisung, um das Auslösen von Ausnahmen ein bisschen schöner zu machen. Definieren Sie einen neuen Kontextmanager (Sie müssen dies nur einmal tun) mit:Jetzt können Sie diesen Kontextmanager wie folgt verwenden:
Vorteile: (1) Es ist etwas sauberer (kein expliziter Try-außer-Block) und (2) Sie erhalten eine benutzerdefinierte
Exception
Unterklasse für jede Verwendung vonnested_break
; Sie müssen nichtException
jedes Mal Ihre eigene Unterklasse deklarieren .quelle
Zunächst können Sie auch in Betracht ziehen, den Prozess zum Abrufen und Validieren der Eingabe zu einer Funktion zu machen. Innerhalb dieser Funktion können Sie den Wert einfach zurückgeben, wenn er korrekt ist, und wenn nicht , in der while- Schleife weiterdrehen. Dies vermeidet im Wesentlichen das von Ihnen gelöste Problem und kann normalerweise im allgemeineren Fall angewendet werden (Ausbrechen mehrerer Schleifen). Wenn Sie diese Struktur unbedingt in Ihrem Code behalten müssen und sich wirklich nicht mit Buchhaltungs-Booleschen Werten befassen möchten ...
Sie können goto auch folgendermaßen verwenden (mit einem April Fools-Modul von hier ):
Ich weiß, ich weiß, "du sollst nicht goto verwenden" und all das, aber es funktioniert gut in seltsamen Fällen wie diesen.
quelle
Führen Sie eine neue Variable ein, die Sie als "Loop Breaker" verwenden. Weisen Sie ihm zuerst etwas zu (False, 0 usw.) und ändern Sie dann innerhalb der äußeren Schleife, bevor Sie davon abbrechen, den Wert in etwas anderes (True, 1, ...). Sobald die Schleife beendet ist, überprüfen Sie die 'übergeordnete' Schleife auf diesen Wert. Lassen Sie mich demonstrieren:
Wenn Sie eine Endlosschleife haben, ist dies der einzige Ausweg. Bei anderen Schleifen ist die Ausführung sehr viel schneller. Dies funktioniert auch, wenn Sie viele verschachtelte Schleifen haben. Sie können alle oder nur einige beenden. Endlose Möglichkeiten! Hoffe das hat geholfen!
quelle
Verwenden Sie eine "simulierte goto-Anweisung" mit der integrierten StopIteration-Ausnahme , um aus mehreren verschachtelten Schleifen auszubrechen, ohne sie in eine Funktion umzuwandeln :
In dieser Diskussion wird die Verwendung von goto-Anweisungen zum Aufbrechen verschachtelter Schleifen beschrieben.
quelle
oder etwas ähnliches. Sie können eine Variable in der inneren Schleife festlegen und sie unmittelbar nach dem Beenden der inneren Schleife in der äußeren Schleife überprüfen und gegebenenfalls unterbrechen. Ich mag die GOTO-Methode, vorausgesetzt, es macht Ihnen nichts aus, ein Aprilscherz-Modul zu verwenden - es ist nicht pythonisch, aber es macht Sinn.
quelle
Dies ist nicht der schönste Weg, aber meiner Meinung nach ist es der beste Weg.
Ich bin mir ziemlich sicher, dass Sie auch hier etwas mit Rekursion herausfinden können, aber ich weiß nicht, ob das eine gute Option für Sie ist.
quelle
Und warum nicht weiter schleifen, wenn zwei Bedingungen erfüllt sind? Ich denke, das ist ein pythonischerer Weg:
Ist es nicht?
Alles Gute.
quelle
while dejaVu:
? Sie setzen es trotzdem auf true.True
Bedingungen darüber nachgedacht , zwei Schleifen zu überspringen, aber nur eine ist genug.if not dejaVu: break
unten gelöst werden und damit die Hauptschleife verlassen? Ich denke, die Lösung kommt der Frage am nächsten. +1Berücksichtigen Sie Ihre Schleifenlogik in einem Iterator, der die Schleifenvariablen liefert und nach Abschluss zurückgibt. Hier ist eine einfache Methode, die Bilder in Zeilen / Spalten anordnet, bis keine Bilder mehr vorhanden sind oder keine Stellen mehr vorhanden sind, an denen sie abgelegt werden können:
Dies hat den Vorteil, dass die komplizierte Schleifenlogik und die Verarbeitung ...
quelle
In diesem Fall ist, wie auch von anderen betont, die funktionale Zerlegung der richtige Weg. Code in Python 3:
quelle
In der Python-
while ... else
Struktur gibt es einen versteckten Trick, mit dem die doppelte Unterbrechung ohne große Codeänderungen / -ergänzungen simuliert werden kann. Wenn diewhile
Bedingung falsch ist, wird derelse
Block im Wesentlichen ausgelöst. Weder Ausnahmencontinue
nochbreak
denelse
Block auslösen . Weitere Informationen finden Sie unter Antworten auf " Else-Klausel in Python while-Anweisung " oder in Python doc on while (v2.7) .Der einzige Nachteil ist, dass Sie die Doppelbruchbedingung in die
while
Bedingung verschieben müssen (oder eine Flagvariable hinzufügen müssen). Variationen davon gibt es auch für diefor
Schleife, bei der derelse
Block nach Abschluss der Schleife ausgelöst wird.quelle
How to break out of multiple loops in Python?
Nach meinem Verständnis war die Frage und die Antwort hätte lauten sollen: "Es funktioniert nicht, probieren Sie etwas anderes aus." Ich weiß, dass es das genau gegebene Beispiel des OP behebt, aber ihre Frage nicht beantwortet.Eine andere Möglichkeit, Ihre Iteration auf eine einstufige Schleife zu reduzieren, besteht in der Verwendung von Generatoren, wie auch in der Python-Referenz angegeben
Sie können es für die Schleife auf eine beliebige Anzahl von Ebenen skalieren
Der Nachteil ist, dass Sie nicht mehr nur ein einziges Level durchbrechen können. Alles oder Nichts.
Ein weiterer Nachteil ist, dass es mit einer while-Schleife nicht funktioniert. Ich wollte diese Antwort ursprünglich auf Python posten - `break` aus allen Schleifen, aber leider ist das als Duplikat dieser geschlossen
quelle
Mein Grund, hierher zu kommen, ist, dass ich eine äußere und eine innere Schleife hatte:
Wie Sie sehen können, geht es nicht zum nächsten x, sondern zum nächsten y.
Um dies zu lösen, musste ich das Array stattdessen zweimal durchlaufen:
Ich weiß, dass dies ein spezieller Fall von OPs Frage war, aber ich poste ihn in der Hoffnung, dass er jemandem hilft, über sein Problem anders nachzudenken und die Dinge einfach zu halten.
quelle
break
anstelle voncontinue
das tun, was Sie wollen, nicht wahr? :-)Versuchen Sie es mit einem unendlichen Generator.
quelle
Mit einer Funktion:
Versuchen Sie, die obigen Codes auszuführen, indem Sie auch die auskommentieren
return
.Ohne Verwendung einer Funktion:
Führen Sie nun die obigen Codes wie bisher aus und versuchen Sie dann, jede Zeile, die jeweils eine Zeile enthält,
break
von unten auskommentieren.quelle
Eine einfache Möglichkeit, mehrere Schleifen in eine einzige, zerbrechliche Schleife umzuwandeln, ist die Verwendung
numpy.ndindex
Sie müssen in Ihre Objekte indizieren, anstatt die Werte explizit durchlaufen zu können, aber zumindest in einfachen Fällen scheint es ungefähr 2-20 Mal einfacher zu sein als die meisten der vorgeschlagenen Antworten.
quelle
quelle
Wahrscheinlich reicht ein kleiner Trick wie unten, wenn Sie es nicht vorziehen, in die Funktion umzugestalten
1 break_level-Variable hinzugefügt, um die while-Schleifenbedingung zu steuern
quelle
Sie können eine Variable definieren (z. B. break_statement ), sie dann in einen anderen Wert ändern, wenn eine Zwei-Unterbrechungsbedingung auftritt, und sie in der if-Anweisung verwenden, um auch von der zweiten Schleife abzubrechen.
quelle
Ich möchte Sie daran erinnern, dass Funktionen in Python direkt in der Mitte des Codes erstellt werden können und transparent auf die umgebenden Variablen zum Lesen und mit
nonlocal
oderglobal
Deklaration zum Schreiben zugreifen können .Sie können also eine Funktion als "zerbrechliche Kontrollstruktur" verwenden und einen Ort definieren, an den Sie zurückkehren möchten:
quelle
Lösungen auf 2 Arten
Mit einem Beispiel: Sind diese beiden Matrizen gleich / gleich?
Matrix1 und Matrix2 haben die gleiche Größe, n, 2 dimensionale Matrizen.
Erste Lösung , ohne Funktion
Zweite Lösung , mit einer Funktion
Dies ist die letzte Lösung für meinen Fall
Einen schönen Tag noch!
quelle
quelle
Hoffentlich hilft das:
quelle
Hier ist eine Implementierung, die zu funktionieren scheint:
Der einzige Nachteil ist, dass Sie
break_
vor den Schleifen definieren müssen .quelle
Der Kredit geht an Vivek Nagarajan, Programmierer seit 1987
Funktion verwenden
Flag verwenden
quelle
Ähnlich wie zuvor, aber kompakter. (Boolesche Werte sind nur Zahlen)
quelle
Da diese Frage zu einer Standardfrage für das Einbrechen in eine bestimmte Schleife geworden ist, möchte ich meine Antwort anhand eines Beispiels geben
Exception
.Obwohl es in Konstrukten mit mehreren Schleifen keine Bezeichnung mit dem Namen "Breaking of Loop" gibt, können wir benutzerdefinierte Ausnahmen verwenden , um in eine bestimmte Schleife unserer Wahl einzubrechen . Betrachten Sie das folgende Beispiel, in dem wir alle Zahlen mit bis zu 4 Ziffern im Basis-6-Nummerierungssystem drucken:
Wenn wir die Ausgabe drucken, erhalten wir niemals einen Wert, dessen Einheitsplatz bei 4 liegt. In diesem Fall brechen wir keine Schleife ab,
BreakLoop(4)
die ausgelöst und in derselben Schleife abgefangen wird. In ähnlicher Weise brechen wir immer dann, wenn zehn Plätze 3 haben, mit in die dritte Schleife einBreakLoop(3)
. Immer wenn hundertBreakLoop(2)
Stellen 5 haben, brechen wir mit in die zweite Schleife ein, und wenn die tausend Stellen 2 haben, brechen wir mit in die erste Schleife einBreakLoop(1)
.Kurz gesagt, erhöhen Sie Ihre Ausnahme (eingebaut oder benutzerdefiniert) in den inneren Schleifen und fangen Sie sie in der Schleife ab, von der aus Sie Ihre Kontrolle wieder aufnehmen möchten. Wenn Sie alle Schleifen unterbrechen möchten, fangen Sie die Ausnahme außerhalb aller Schleifen ab. (Ich habe diesen Fall im Beispiel nicht gezeigt).
quelle