Why does python use 'else' after for and while loops?

前端 未结 21 1862
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-21 06:57

I understand how this construct works:

for i in range(10):
    print(i)

    if i == 9:
        print(\"Too big - I\'m         


        
相关标签:
21条回答
  • 2020-11-21 07:19

    Because they didn't want to introduce a new keyword to the language. Each one steals an identifier and causes backwards compatibility problems, so it's usually a last resort.

    0 讨论(0)
  • 2020-11-21 07:21

    Since the technical part has been pretty much answered, my comment is just in relation with the confusion that produce this recycled keyword.

    Being Python a very eloquent programming language, the misuse of a keyword is more notorious. The else keyword perfectly describes part of the flow of a decision tree, "if you can't do this, (else) do that". It's implied in our own language.

    Instead, using this keyword with while and for statements creates confusion. The reason, our career as programmers has taught us that the else statement resides within a decision tree; its logical scope, a wrapper that conditionally return a path to follow. Meanwhile, loop statements have a figurative explicit goal to reach something. The goal is met after continuous iterations of a process.

    if / else indicate a path to follow. Loops follow a path until the "goal" is completed.

    The issue is that else is a word that clearly define the last option in a condition. The semantics of the word are both shared by Python and Human Language. But the else word in Human Language is never used to indicate the actions someone or something will take after something is completed. It will be used if, in the process of completing it, an issue rises (more like a break statement).

    At the end, the keyword will remain in Python. It's clear it was mistake, clearer when every programmer tries to come up with a story to understand its usage like some mnemonic device. I'd have loved if they have chosen instead the keyword then. I believe that this keyword fits perfectly in that iterative flow, the payoff after the loop.

    It resembles that situation that some child has after following every step in assembling a toy: And THEN what Dad?

    0 讨论(0)
  • 2020-11-21 07:23
    for i in range(3):
        print(i)
    
        if i == 2:
            print("Too big - I'm giving up!")
            break;
    else:
        print("Completed successfully")
    

    "else" here is crazily simple, just mean

    1, "if for clause is completed"

    for i in range(3):
        print(i)
    
        if i == 2:
            print("Too big - I'm giving up!")
            break;
    if "for clause is completed":
        print("Completed successfully")
    

    It's wielding to write such long statements as "for clause is completed", so they introduce "else".

    else here is a if in its nature.

    2, However, How about for clause is not run at all

    In [331]: for i in range(0):
         ...:     print(i)
         ...: 
         ...:     if i == 9:
         ...:         print("Too big - I'm giving up!")
         ...:         break
         ...: else:
         ...:     print("Completed successfully")
         ...:     
    Completed successfully
    

    So it's completely statement is logic combination:

    if "for clause is completed" or "not run at all":
         do else stuff
    

    or put it this way:

    if "for clause is not partially run":
        do else stuff
    

    or this way:

    if "for clause not encounter a break":
        do else stuff
    
    0 讨论(0)
  • 2020-11-21 07:24

    I agree, it's more like an 'elif not [condition(s) raising break]'.

    I know this is an old thread, but I am looking into the same question right now, and I'm not sure anyone has captured the answer to this question in the way I understand it.

    For me, there are three ways of "reading" the else in For... else or While... else statements, all of which are equivalent, are:

    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) (presumably there is such a condition, or you wouldn't have a loop)

    So, essentially, the "else" in a loop is really an "elif ..." where '...' is (1) no break, which is equivalent to (2) NOT [condition(s) raising break].

    I think the key is that the else is pointless without the 'break', so a for...else includes:

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

    So, essential elements of a for...else loop are as follows, and you would read them in plainer English as:

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

    As the other posters have said, a break is generally raised when you are able to locate what your loop is looking for, so the else: becomes "what to do if target item not located".

    Example

    You can also use exception handling, breaks, and for loops all together.

    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")
    

    Result

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

    Example

    Simple example with a break being hit.

    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")
    

    Result

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

    Example

    Simple example where there no break, no condition raising a break, and no error are encountered.

    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")
    

    Result

    z: 0
    z: 1
    z: 2
    z_loop complete without break or error
    ----------
    
    0 讨论(0)
  • 2020-11-21 07:25

    A common construct is to run a loop until something is found and then to break out of the loop. The problem is that if I break out of the loop or the loop ends I need to determine which case happened. One method is to create a flag or store variable that will let me do a second test to see how the loop was exited.

    For example assume that I need to search through a list and process each item until a flag item is found and then stop processing. If the flag item is missing then an exception needs to be raised.

    Using the Python for...else construct you have

    for i in mylist:
        if i == theflag:
            break
        process(i)
    else:
        raise ValueError("List argument missing terminal flag.")
    

    Compare this to a method that does not use this syntactic sugar:

    flagfound = False
    for i in mylist:
        if i == theflag:
            flagfound = True
            break
        process(i)
    
    if not flagfound:
        raise ValueError("List argument missing terminal flag.")
    

    In the first case the raise is bound tightly to the for loop it works with. In the second the binding is not as strong and errors may be introduced during maintenance.

    0 讨论(0)
  • 2020-11-21 07:26

    I was just trying to make sense of it again myself. I found that the following helps!

    • Think of the else as being paired with the if inside the loop (instead of with the for) - if condition is met then break the loop, else do this - except it's one else paired with multiple ifs!
    • If no ifs were satisfied at all, then do the else.
    • The multiple ifs can also actually be thought of as if-elifs!

    0 讨论(0)
提交回复
热议问题