757 Stimmen

Warum verwendet Python "else" nach for- und while-Schleifen?

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 wird hier als Schlüsselwort verwendet, da es nahelegt, dass der betreffende Code nur ausgeführt wird, wenn die for Block wird nicht abgeschlossen, was das Gegenteil von dem ist, was er tut! Egal, wie ich darüber denke, mein Gehirn kann nicht nahtlos von der for Anweisung an den else blockieren. Für mich, continue o continuewith wäre sinnvoller (und ich versuche, mich darauf einzustellen, es so zu lesen).

Ich frage mich, wie Python-Programmierer dieses Konstrukt in ihrem Kopf (oder laut, wenn Sie wollen) lesen. Vielleicht übersehe ich etwas, das solche Codeblöcke leichter entzifferbar machen würde?


Diese Frage bezieht sich auf die <em>zugrundeliegende Entwurfsentscheidung </em>d.h. <em>warum sie nützlich ist </em>um diesen Code schreiben zu können. Siehe auch <a href="https://stackoverflow.com/questions/3295938">Else-Klausel in der Python-Anweisung while </a>für die spezifische Frage nach <em>was die Syntax bedeutet </em>.

10voto

Gabriel Staples Punkte 20228

Ich frage mich, wie Python-Programmierer dieses Konstrukt in ihrem Kopf (oder laut, wenn Sie wollen) lesen.

Ich denke einfach in meinem Kopf:

"sonst nein break angetroffen wurde..."

Das war's!

Dies liegt daran, dass die else Klausel wird nur ausgeführt, wenn eine break Anweisung wurde NICHT in der for Schleife.

Referenz:

Siehe hier: https://book.pythontips.com/en/latest/for_-_else.html#else-clause (Hervorhebung hinzugefügt, und "nicht" wurde in "NICHT" geändert):

for Schleifen haben auch eine else Klausel, die den meisten von uns nicht bekannt ist. En else Klausel wird ausgeführt, nachdem die Schleife normal beendet wurde. Dies bedeutet, dass die Schleife NICHT auf eine Break-Anweisung gestoßen ist.


Ich empfehle daher gegen diese ungewöhnliche Eigenschaft der Sprache zu nutzen. Verwenden Sie nicht die else Klausel nach einer for-Schleife. Das ist für die meisten Menschen verwirrend und verlangsamt nur ihre Fähigkeit, den Code zu lesen und zu verstehen.

7voto

0xc0de Punkte 7588

Ich lese es wie "Wenn die iterable vollständig erschöpft ist und die Ausführung mit der nächsten Anweisung fortgesetzt werden soll, nachdem die for wird die else-Klausel ausgeführt." Wenn also die Iteration unterbrochen wird durch break wird diese nicht ausgeführt.

6voto

cizixs Punkte 11153

En else Schlüsselwort kann hier verwirrend sein, und wie viele Leute darauf hingewiesen haben, ist etwas wie nobreak , notbreak angemessener ist.

Um zu verstehen for ... else ... logischerweise vergleichen mit try...except...else , nicht if...else... Die meisten Python-Programmierer sind mit dem folgenden Code vertraut:

try:
    do_something()
except:
    print("Error happened.") # The try block threw an exception
else:
    print("Everything is find.") # The try block does things just find.

Denken Sie in ähnlicher Weise an break als eine besondere Art von Exception :

for x in iterable:
    do_something(x)
except break:
    pass # Implied by Python's loop semantics
else:
    print('no break encountered')  # No break statement was encountered

Der Unterschied ist python impliziert except break und man kann es nicht ausschreiben, also wird es:

for x in iterable:
    do_something(x)
else:
    print('no break encountered')  # No break statement was encountered

Ja, ich weiß, dass dieser Vergleich schwierig und ermüdend sein kann, aber er verdeutlicht die Verwirrung.

6voto

NotAnAmbiTurner Punkte 2086

Ich stimme zu, es ist mehr wie ein 'elif not [condition(s) raising break]'.

Ich weiß, dass dies ein altes Thema ist, aber ich beschäftige mich gerade mit der gleichen Frage, und ich bin mir nicht sicher, ob jemand die Antwort auf diese Frage so erfasst hat, wie ich sie verstehe.

Für mich gibt es drei Möglichkeiten, den Text zu "lesen" else en For... else o While... else Anweisungen, die alle gleichwertig sind, sind:

  1. else == if the loop completes normally (without a break or error)
  2. else == if the loop does not encounter a break
  3. else == else not (condition raising break) (Vermutlich gibt es eine solche Bedingung, sonst gäbe es keine Schleife)

Im Wesentlichen ist das "else" in einer Schleife also ein "elif ...", wobei "..." (1) kein Abbruch ist, was (2) NICHT [Bedingung(en), die Abbruch auslösen] entspricht.

Ich denke, der Schlüssel ist, dass die else ist ohne die "Unterbrechung" sinnlos, so dass eine for...else umfasst:

for:
    do stuff
    conditional break # implied by else
else not break:
    do more stuff

Wesentliche Elemente einer for...else Die Schleifen lauten wie folgt, und in einfacherem Englisch lauten sie wie folgt:

for:
    do stuff
    condition:
        break
else: # read as "else not break" or "else not condition"
    do more stuff

Wie die anderen Poster bereits sagten, wird eine Unterbrechung in der Regel dann ausgelöst, wenn Sie in der Lage sind, das zu finden, wonach Ihre Schleife sucht, so dass die else: wird zu "was ist zu tun, wenn das Zielobjekt nicht gefunden wird".

Beispiel

Sie können auch Ausnahmebehandlung, Pausen und for-Schleifen zusammen verwenden.

for x in range(0,3):
    print("x: {}".format(x))
    if x == 2:
        try:
            raise AssertionError("ASSERTION ERROR: x is {}".format(x))
        except:
            print(AssertionError("ASSERTION ERROR: x is {}".format(x)))
            break
else:
    print("X loop complete without error")

Ergebnis

x: 0
x: 1
x: 2
ASSERTION ERROR: x is 2
----------
# loop not completed (hit break), so else didn't run

Beispiel

Ein einfaches Beispiel mit einer Pause, die getroffen wird.

for y in range(0,3):
    print("y: {}".format(y))
    if y == 2: # will be executed
        print("BREAK: y is {}\n----------".format(y))
        break
else: # not executed because break is hit
    print("y_loop completed without break----------\n")

Ergebnis

y: 0
y: 1
y: 2
BREAK: y is 2
----------
# loop not completed (hit break), so else didn't run

Beispiel

Einfaches Beispiel, bei dem keine Unterbrechung, keine Bedingung, die eine Unterbrechung auslöst, und kein Fehler auftritt.

for z in range(0,3):
     print("z: {}".format(z))
     if z == 4: # will not be executed
         print("BREAK: z is {}\n".format(y))
         break
     if z == 4: # will not be executed
         raise AssertionError("ASSERTION ERROR: x is {}".format(x))
else:
     print("z_loop complete without break or error\n----------\n")

Ergebnis

z: 0
z: 1
z: 2
z_loop complete without break or error
----------

5voto

GoingMyWay Punkte 15426

Codes in else Anweisungsblock wird ausgeführt, wenn die for Schleife war nicht kaputt.

for x in xrange(1,5):
    if x == 5:
        print 'find 5'
        break
else:
    print 'can not find 5!'
#can not find 5!

Von der docs: break- und continue-Anweisungen und else-Klauseln in Schleifen

Schleifenanweisungen können eine else-Klausel haben; sie wird ausgeführt, wenn die Schleife durch Erschöpfung der Liste (bei for) oder wenn die Bedingung falsch wird (bei while), aber nicht, wenn die Schleife durch eine break-Anweisung beendet wird. Dies wird durch die folgende Schleife veranschaulicht, die nach Primzahlen sucht:

>>> for n in range(2, 10):
...     for x in range(2, n):
...         if n % x == 0:
...             print(n, 'equals', x, '*', n//x)
...             break
...     else:
...         # loop fell through without finding a factor
...         print(n, 'is a prime number')
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

(Ja, das ist der richtige Code. Sehen Sie genau hin: Die else-Klausel gehört zur for-Schleife, nicht zur if-Anweisung).

Bei der Verwendung in einer Schleife hat die else-Klausel mehr mit der else-Klausel einer try-Anweisung gemeinsam als mit der if-Anweisung: Die else-Klausel einer try-Anweisung wird ausgeführt, wenn keine Ausnahme auftritt, und die else-Klausel einer Schleife wird ausgeführt, wenn kein Abbruch erfolgt. Weitere Informationen über die try-Anweisung und Ausnahmen finden Sie unter Behandlung von Ausnahmen.

Die continue-Anweisung, ebenfalls aus C entlehnt, setzt die nächste Iteration der Schleife fort:

>>> for num in range(2, 10):
...     if num % 2 == 0:
...         print("Found an even number", num)
...         continue
...     print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9

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