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

Chris Angelico rosuav at gmail.com
Fri Nov 3 12:24:42 EDT 2017


On Sat, Nov 4, 2017 at 3:15 AM, Alexey Muranov <alexey.muranov at gmail.com> wrote:
> On Fri, 2017-11-03 at 22:03 +1100, Chris Angelico wrote:
>> On Fri, Nov 3, 2017 at 8:48 PM, Alexey Muranov <alexey.muranov at gmail.
>> com> wrote:
>> > 'Then' describes what happens next indeed, unless some
>> > extraordinary
>> > situation prevents it from happening, for example:
>> >
>> >     try:
>> >         go_to_the_bakery()
>> >     then:
>> >         buy_croissants(2)
>> >     except BakeryClosed:
>> >         go_to_the_grociery()
>> >         buy_baguette(1)
>> >     finally:
>> >         come_back()
>> >
>> > I know this is a poor program example (why not to use a boolean
>> > return value
>> > instead of an exception, etc.), and i know that currently in Python
>> > `except`
>> > must precede `else`, it is just to illustrate the choice of terms.
>>
>> What is the semantic difference between that code and the same
>> without the "then:"?
>
> Chris,
>
> the semantic difference is that their meanings/behaviours are not identical
> (i imply that `then` here does what `else` currently does).  I agree however
> that from practical viewpoint the difference will probably never be
> observable (unless the person enters the bakery and asks for croissants, but
> during this time the baker exits the bakery and closes it to go on
> vacation).

Okay, so what you're doing is taking the current "try/else" semantics,
and hoisting the "happy path" up to immediately underneath the part
guarded by the try. That's not unreasonable, but also not a huge
advantage. It's basically saying:

try:
    do_stuff
except None: # let's pretend
    print("all is well")
except ValueError:
    print("do_stuff has the wrong value")
finally:
    print("we're done")

But if the difference between this and the current layout (with "else"
coming *after* the except blocks) is significant to you, I would
recommend refactoring the try/finally into a context manager:

with car_trip() as trip:
    try:
        trip.goto(bakery)
        buy_croissants(2)
    except BakeryClosed:
        trip.goto(grocery)
        buy_baguette(1)

The context manager takes care of bringing us home unconditionally,
leaving us with cleaner logic.

ChrisA



More information about the Python-list mailing list