replacing `else` with `then` in `for` and `try`

Steve D'Aprano steve+python at pearwood.info
Sun Nov 5 21:28:39 EST 2017


On Sat, 4 Nov 2017 03:57 pm, Michael Torrie wrote:

> On 11/03/2017 09:06 PM, Chris Angelico wrote:
>> On Sat, Nov 4, 2017 at 1:57 PM, Michael Torrie <torriem at gmail.com> wrote:
>>> On 11/03/2017 07:09 PM, Steve D'Aprano wrote:
>>>> On Sat, 4 Nov 2017 06:15 am, Michael Torrie wrote:
>>>>
>>>>> In fact if you have no break you may as well drop the
>>>>> else entirely, because the block will always execute.
>>>>
>>>> That's incorrect. There are multiple ways to exit a loop that will
>>>> prevent the `else` block from executing, `break` is only one.
>>>
>>> Such as?
>> 
>> There are many. But other than break, I don't know of any that WOULD
>> execute the next line of code immediately _after_ the loop.
> 
> Can you be more specific? What are some of these "many" ways of aborting
> a loop?  Help a guy out here.

Aside from more exotic methods such as os.abort, os._exit and signal handlers,
the common ways of breaking out of a loop are:

- raise
- return
- break

Am I being pedantic? Of course I am. But we're programmers -- if we don't have
an accurate and complete understanding of code, who will? Given how many
people find it difficult to understand the semanics of for...else, I think we
need to be pedantic about it.

I raise these because such commonplace ways of exiting a loop rules out
suggestions that we think of or rename `else` as "else no break"
or "finally":

(1) `else no break` is misleading as it implies that `break` is the only way
to avoid running the block;

(2) `finally` is misleading as it suggests that the block runs even when you
raise or return out of the loop, like a try...finally block.


> I know, for example, that we have exceptions. But those hardly matter in
> this discussion because they wouldn't execute the else clause either.

That contradicts what you said earlier:

    "if you have no break the [else] block will always execute."

Of course you are right -- an exception will also prevent the `else` clause
from running. But that's not what you said earlier. Hence my correction.

The fact that `raise` and `return` avoid running the `else` block is not a
given. We cannot afford to say "that's so obvious it doesn't need to be
said". It isn't obvious. There are at least two other code blocks that make
guarantees about code "always"[1] running, even if you raise or return:

- in a try...except...else block, the `finally` block will still run;

- in a `with` block, the context manager's `__exit__` method will usually run
(it depends on the context manager).



[1] For reasonable values of "always". Obviously if you drop a 1000 tonne
weight on the computer, the `finally` clause will not get a chance to run
before the CPU is crushed into powder :-)


-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list