739 Stimmen

Wie kann man aus den Mehrfachschleifen ausbrechen?

Bei folgendem Code (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, dies zu erreichen? Oder muss ich eine Prüfung durchführen, um aus der Eingabeschleife auszubrechen, und dann eine weitere, eingeschränktere Prüfung in der äußeren Schleife, um alles zusammen auszubrechen, wenn der Benutzer zufrieden ist?

193 Stimmen

Warum gibt es in Python nicht einfach "break(n)", wobei n die Anzahl der Ebenen ist, aus denen man ausbrechen möchte.

14 Stimmen

C++ ist hier schön mit goto wenn Sie tief in eine Menge von Schleifen eingebettet sind

2 Stimmen

68voto

Mark Dickinson Punkte 26875

Ich neige dazu, zuzustimmen, dass Refactoring in eine Funktion ist in der Regel der beste Ansatz für diese Art von Situation, aber für, wenn Sie wirklich Wenn Sie aus verschachtelten Schleifen ausbrechen müssen, finden Sie hier eine interessante Variante des von @S. Lott beschriebenen Ansatzes zur Erzeugung von Ausnahmen. Sie verwendet Pythons with Anweisung, um das Anheben von Ausnahmen ein wenig schöner aussehen zu lassen. Definieren Sie einen neuen Kontextmanager (Sie müssen dies nur einmal tun) mit:

from contextlib import contextmanager
@contextmanager
def nested_break():
    class NestedBreakException(Exception):
        pass
    try:
        yield NestedBreakException
    except NestedBreakException:
        pass

Nun können Sie diesen Kontextmanager wie folgt verwenden:

with nested_break() as mylabel:
    while True:
        print "current state"
        while True:
            ok = raw_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": raise mylabel
            if ok == "n" or ok == "N": break
        print "more processing"

Vorteile: (1) es ist etwas sauberer (kein expliziter Try-Except-Block), und (2) Sie erhalten eine maßgeschneiderte Exception Unterklasse für jede Verwendung von nested_break ; keine Notwendigkeit, eine eigene Erklärung abzugeben Exception Unterklasse jedes Mal.

48voto

Matt J Punkte 41229

Zunächst können Sie auch in Betracht ziehen, den Prozess des Erhaltens und Validierens der Eingabe zu einer Funktion zu machen; innerhalb dieser Funktion können Sie den Wert einfach zurückgeben, wenn er korrekt ist, und die Spinnerei in der während Schleife, wenn nicht. Damit ist das Problem, das Sie gelöst haben, im Wesentlichen gelöst und kann in der Regel auch im allgemeineren Fall (Ausbrechen aus mehreren Schleifen) angewendet werden. Wenn Sie diese Struktur unbedingt in Ihrem Code beibehalten müssen und sich wirklich nicht mit buchhalterischen Booleschen Werten beschäftigen wollen...

Sie können auch Folgendes verwenden siehe auf folgende Weise (unter Verwendung eines Aprilscherz-Moduls von ici ):

#import the stuff
from goto import goto, label

while True:
    #snip: print out current state
    while True:
        ok = get_input("Is this ok? (y/n)")
        if ok == "y" or ok == "Y": goto .breakall
        if ok == "n" or ok == "N": break
    #do more processing with menus and stuff
label .breakall

Ich weiß, ich weiß, "Du sollst nicht goto verwenden" und so weiter, aber in seltsamen Fällen wie diesem funktioniert es gut.

45voto

Justas Punkte 5208

Um aus mehreren verschachtelten Schleifen auszubrechen, ohne in eine Funktion umzuwandeln, verwenden Sie eine "simulierte goto-Anweisung" mit der eingebauten StopIteration-Ausnahme :

try:
    for outer in range(100):
        for inner in range(100):
            if break_early():
                raise StopIteration

except StopIteration: pass

Voir diese Diskussion über die Verwendung von goto-Anweisungen für den Ausstieg aus verschachtelten Schleifen.

23voto

quick_dry Punkte 766
keeplooping = True
while keeplooping:
    # Do stuff
    while keeplooping:
          # Do some other stuff
          if finisheddoingstuff():
              keeplooping = False

oder so ähnlich.

Sie könnten eine Variable in der inneren Schleife setzen und sie in der äußeren Schleife unmittelbar nach Beendigung der inneren Schleife überprüfen und gegebenenfalls abbrechen. Ich mag die GOTO-Methode, vorausgesetzt, es macht Ihnen nichts aus, ein Modul für einen Aprilscherz zu verwenden - es ist nicht pythonisch, aber es macht Sinn.

13voto

Jason Baker Punkte 180981

Das ist zwar nicht die schönste, aber meiner Meinung nach die beste Art, das zu tun.

def loop():
    while True:
    #snip: print out current state
        while True:
            ok = get_input("Is this ok? (y/n)")
            if ok == "y" or ok == "Y": return
            if ok == "n" or ok == "N": break
        #do more processing with menus and stuff

Ich bin mir ziemlich sicher, dass man auch hier etwas mit Rekursion ausarbeiten könnte, aber ich weiß nicht, ob das eine gute Option für Sie ist.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X