Behavior of the for-else construct

Rob Cliffe rob.cliffe at btinternet.com
Thu Mar 3 20:43:38 EST 2022



On 04/03/2022 00:43, Chris Angelico wrote:
> On Fri, 4 Mar 2022 at 11:14, Rob Cliffe via Python-list
> <python-list at python.org> wrote:
>> I find it so hard to remember what `for ... else` means that on the very
>> few occasions I have used it, I ALWAYS put a comment alongside/below the
>> `else` to remind myself (and anyone else unfortunate enough to read my
>> code) what triggers it, e.g.
>>
>>       for item in search_list:
>>           ...
>>           ... break
>>       else: # if no item in search_list matched the criteria
> A "break" statement always takes you to the line following the current
> loop construct. The "else" block is part of the current loop
> construct. It's no more a "no-break" block than the body of the for
> loop is a "no-break" body here:
>
> for item in stuff:
>      if condition: break
>      frobnicate(item) # if no previous item matched the condition
>
>> You get the idea.
>> If I really want to remember what this construct means, I remind myself
>> that `else` here really means `no break`.  Would have been better if it
>> had been spelt `nobreak` or similar in the first place.
> Maybe, but I think that obscures the meaning of it; "finally" isn't
> quite right either (in a try block, you'd hit a finally block whether
> you raise an exception or not), but I think it's closer. Creating a
> new language keyword is an incredibly high cost.
>
> Think of it like this:
>
> for item in search_list:
>      if condition: pass
>      else:
>          print("Condition not true for this item")
>
> for item in search_list:
>      if condition: break
> else:
>      print("Condition not true for any item")
>
> There's a parallel here. Since a for-else loop is basically useless
> without an if-break construct inside it,
Yes but you have to remember what for-else means even to grasp that point.
>   the else clause can be
> thought of as the else on a massive if/elif chain:
>
> if stuff[0].is_good:
>      print("This item is good", stuff[0])
> elif stuff[1].is_good:
>      print("This item is good", stuff[1])
> ...
> ...
> elif stuff[n].is_good:
>      print("This item is good", stuff[n])
> else:
>      print("All items are bad")
>
> As a loop, this looks like this:
>
> for item in stuff:
>      if item.is_good:
>          print("This item is good", item)
>          break
> else:
>      print("All items are bad")
>
> The else is attached to the for so that it compasses ALL the if
> statements, but it's still broadly saying "do this when we don't hit
> the 'if' condition".
>
> Whether that's a sufficient mnemonic, I don't know,
Not for me, I'm afraid.
>   but it doesn't
> really matter; the construct is useful to those of us who want it, and
> if other people ignore it, that's fine. Nobody ever said you had to
> use or understand every single feature of the language you're using.
>
> ChrisA



More information about the Python-list mailing list