it-swarm.com.de

Python: Fortsetzung der nächsten Iteration in der äußeren Schleife

Ich wollte wissen, ob es in Python eingebaute Möglichkeiten gibt, mit der nächsten Iteration in der äußeren Schleife fortzufahren. Betrachten Sie zum Beispiel den Code:

for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            continue
    ...block1...

Ich möchte, dass diese continue-Anweisung die jj-Schleife verlässt und zum nächsten Element in der ii-Schleife wechselt. Ich kann diese Logik auch auf andere Weise implementieren (durch Setzen einer Flag-Variablen), aber gibt es eine einfache Möglichkeit, dies zu tun, oder ist es so, dass man zu viel verlangt?

96
Sahas
for i in ...:
    for j in ...:
        for k in ...:
            if something:
                # continue loop i

In einem allgemeinen Fall können Sie, wenn Sie mehrere Schleifenstufen haben und break für Sie nicht funktioniert (da Sie eine der oberen Schleifen fortsetzen möchten, nicht die oberhalb der aktuellen Schleife), eine der folgenden Aktionen ausführen

Überarbeiten Sie die Schleifen, aus denen Sie eine Funktion verlassen möchten

def inner():
    for j in ...:
        for k in ...:
            if something:
                return


for i in ...:
    inner()

Der Nachteil ist, dass Sie möglicherweise einige Variablen, die zuvor im Gültigkeitsbereich waren, an diese neue Funktion übergeben müssen. Sie können sie entweder einfach als Parameter übergeben, sie als Instanzvariablen für ein Objekt definieren (ein neues Objekt nur für diese Funktion erstellen, wenn dies sinnvoll ist) oder globale Variablen, Singletons oder was auch immer (ehm, ehm).

Oder Sie können inner als verschachtelte Funktion definieren und es einfach erfassen lassen, was es benötigt (möglicherweise langsamer?)

for i in ...:
    def inner():
        for j in ...:
            for k in ...:
                if something:
                    return
    inner()

Verwenden Sie Ausnahmen

Aus philosophischen Gründen gibt es Ausnahmen dafür, dass der Programmfluss bei Bedarf durch die strukturierten Programmierbausteine ​​unterbrochen wird.

Der Vorteil ist, dass Sie den einzelnen Code nicht in mehrere Teile aufteilen müssen. Dies ist gut, wenn es sich um eine Art Berechnung handelt, die Sie beim Schreiben in Python entwerfen. Das Einführen von Abstraktionen zu diesem frühen Zeitpunkt kann Sie verlangsamen.

Schlecht bei diesem Ansatz ist, dass Interpreter/Compiler-Autoren normalerweise davon ausgehen, dass Ausnahmen außergewöhnlich sind und für sie entsprechend optimieren.

class ContinueI(Exception):
    pass


continue_i = ContinueI()

for i in ...:
    try:
        for j in ...:
            for k in ...:
                if something:
                    raise continue_i
    except ContinueI:
        continue

Erstellen Sie hierfür eine spezielle Ausnahmeklasse, damit Sie nicht versehentlich eine andere Ausnahme zum Schweigen bringen.

Etwas ganz anderes

Ich bin mir sicher, dass es noch andere Lösungen gibt.

38
user7610
for ii in range(200):
    for jj in range(200, 400):
        ...block0...
        if something:
            break
    else:
        ...block1...

Break unterbricht die innere Schleife und Block1 wird nicht ausgeführt (es wird nur ausgeführt, wenn die innere Schleife normal beendet wird).

119
culebrón

In anderen Sprachen können Sie die Schleife beschriften und die beschriftete Schleife abbrechen. Python Enhancement Proposal (PEP) 3136 schlug vor, diese zu Python hinzuzufügen aber Guido lehnte es ab :

Ich lehne es jedoch aufgrund der Tatsache ab, dass der Code so kompliziert ist erfordern diese Funktion ist sehr selten. In den meisten Fällen gibt es Problemumgehungen, die sauberen Code erzeugen, beispielsweise mit 'return' . Ich bin mir sicher, dass es einige (seltene) Fälle gibt, in denen die Klarheit der Code würde unter einem Refactoring leiden, das die Verwendung von .__ ermöglicht. Zurück, dies wird durch zwei Probleme ausgeglichen:

  1. Die Komplexität fügt sich der Sprache dauerhaft hinzu. Dies betrifft nicht nur alle Python-Implementierungen, aber auch jedes Quellanalysetool plus natürlich alle Unterlagen für die Sprache.

  2. Meine Erwartung, dass die Funktion mehr missbraucht wird als rechts verwendet, was zu einer Netto-Abnahme der Code-Klarheit führt (gemessen über aller Python-Code wird fortan geschrieben). Faule Programmierer sind überall, und bevor Sie es wissen, haben Sie eine unglaubliche Verwirrung in Ihren Händen von unverständlicher Code.

Wenn Sie also darauf gehofft haben, haben Sie kein Glück, aber schauen Sie sich eine der anderen Antworten an, da es gute Optionen gibt.

36
Dave Webb

Ich denke, du könntest so etwas tun:

for ii in range(200):
    restart = False
    for jj in range(200, 400):
        ...block0...
        if something:
            restart = True
            break
    if restart:
        continue
    ...block1...
11
asmeurer

Ich denke, eine der einfachsten Möglichkeiten, dies zu erreichen, besteht darin, "weiter" durch "break" -Anweisung zu ersetzen, d. H.

for ii in range(200):
 for jj in range(200, 400):
    ...block0...
    if something:
        break
 ...block1...       

Hier ist zum Beispiel der einfache Code, um zu sehen, wie genau es weitergeht:

for i in range(10):
    print("doing outer loop")
    print("i=",i)
    for p in range(10):
        print("doing inner loop")
        print("p=",p)
        if p==3:
            print("breaking from inner loop")
            break
    print("doing some code in outer loop")
1

Eine andere Möglichkeit, mit dieser Art von Problem umzugehen, ist die Verwendung von Exception ().

for ii in range(200):
    try:
        for jj in range(200, 400):
            ...block0...
            if something:
                raise Exception()
    except Exception:
        continue
    ...block1...

Zum Beispiel:

for n in range(1,4):
    for m in range(1,4):
        print n,'-',m

ergebnis:

    1-1
    1-2
    1-3
    2-1
    2-2
    2-3
    3-1
    3-2
    3-3

Angenommen, wir möchten von m Schleife zu der äußeren n Schleife springen, wenn m = 3:

for n in range(1,4):
    try:
        for m in range(1,4):
            if m == 3:
                raise Exception()            
            print n,'-',m
    except Exception:
        continue

ergebnis:

    1-1
    1-2
    2-1
    2-2
    3-1
    3-2

Referenzlink: http://www.programming-idioms.org/idiom/42/continue-outer-loop/1264/python

1
Patrick

Wir wollen etwas finden und dann die innere Wiederholung stoppen. Ich benutze ein Flaggensystem.

for l in f:
    flag = True
    for e in r:
        if flag==False:continue
        if somecondition:
            do_something()
            flag=False
0
Esther

Ich habe einfach so etwas gemacht. Meine Lösung dafür war, die innere for-Schleife durch ein Listenverständnis zu ersetzen. 

for ii in range(200):
    done = any([op(ii, jj) for jj in range(200, 400)])
    ...block0...
    if done:
        continue
    ...block1...

wobei op ein boolescher Operator ist, der auf eine Kombination von ii und jj wirkt. In meinem Fall war ich fertig, wenn eine der Operationen als wahr zurückkehrte.

Das unterscheidet sich wirklich nicht so sehr davon, den Code in eine Funktion zu zerlegen, aber ich dachte, es wäre interessant, den "any" -Operator zu verwenden, um ein logisches OR in einer Liste von Booleschen Operatoren auszuführen. Es vermeidet auch den Funktionsaufruf.

0
cagem12