Replacement for `else` keyword in `try-else` (for ex. `noexcept` or `not except`)

FWIW I stumbled upon a StackOverflow question today where as usual someone new confused the else clause for a for loop with one for an if statement.

And it was marked as a duplicate to this question, which received hundreds of upvotes and which is really a rant about the poor choice of this keyword.

1 Like

As the answer states, it’s fairly intuitive for while loops:

i = 1
while True:
    if i <= 3:
        i += 1
    else: # i > 3
        print("done")
        break

i = 1
while i <= 3:
    i += 1
else: # i > 3
    print("done")

I’ll say that it’s not intuitive for for-loops, as no condition is being evaluated.

2 Likes

Not to beat a dead horse, but I find the best explanation of for/else is that it is naturally used where there is a condition being evaluated:

for thing in container:
    if something_about(thing):
        # Found it!
        do_something(thing)
        break
else:
    # Didn't find it..
    no_such_thing()

I think of the else clause as pairing with the if in the loop. If you conceptually unroll the loop, you have an if/if/if/if/else structure. The if is in the loop, and the else is outside it.

2 Likes

It’s really hard for me to see the syntax of somewhere that’s been present in Python so long changing now.

Part of the issue may be the current documentation is correct but maybe not as clear as it could be:

4.4. break and continue Statements, and else Clauses on Loops

The break statement breaks out of the innermost enclosing for or while loop.

A for or while loop can include an else clause.

In a for loop, the else clause is executed after the loop reaches its final iteration.

In a while loop, it’s executed after the loop’s condition becomes false.

In either kind of loop, the else clause is not executed if the loop was terminated by a break.

I’ve submitted a documentation pull request for the tutorial to say:

4.4. break and continue Statements, and else Clauses on Loops

The break statement breaks out of the innermost enclosing for or while loop.

The break statement may be paired with an else clause. If the loop exits without executing the break, the else clause executes.

In a for loop, the else clause is executed after the loop reaches its final iteration if no break occurred.

In a while loop, it’s executed after the loop’s condition becomes false if no break occurred.

The implicit condition is that the iterator used by the for loop has not raised StopIteration. Something like

# There are lots of ways this could be written...

_iterator = iter(iterable)
_raised = False
while not _raised:
    try:
        x = next(_iterator)
    except StopIteration:
        _raised = True
    else:
        <body>
else:
    <stuff>

for

for  x in iterable:
    <body>
else:
    <stuff>
1 Like

Thanks. That’s indeed a great way to rationalize the for-else construct for novices, perhaps even worthy of a place in the documentation/tutorial.

1 Like

What do you think of this? For-else deserves its own section in the tutorial by nedbat · Pull Request #123946 · python/cpython · GitHub

1 Like

Thanks for the PR. :+1: As a tutorial though I think the concept of “loop unrolling” may sound too foreign to novices. The paragraph should serve the purpose just as well without this sentence.