for -- else: what was the motivation?

Weatherby,Gerard gweatherby at uchc.edu
Mon Oct 10 14:25:19 EDT 2022


pylint, at least, provides a warning:

fe.py:4:0: W0120: Else clause on loop without a break statement (useless-else-on-loop)


sum = 0
for i in range(5):
    sum += i
else:
    print("Always executes")
print(sum)


From: Python-list <python-list-bounces+gweatherby=uchc.edu at python.org> on behalf of Axy via Python-list <python-list at python.org>
Date: Monday, October 10, 2022 at 1:10 PM
To: python-list at python.org <python-list at python.org>
Subject: Re: for -- else: what was the motivation?
*** Attention: This is an external email. Use caution responding, opening attachments or clicking on links. ***

> On 10/10/2022 15:52, Weatherby,Gerard wrote:
>> I wonder if for/else could have been less confusing if it was
>> referred to
>> as for-break-else and if the else clause was only valid syntax if the
>> for
>> loop actually contained a break statement in the first place.
>
> Sounds reasonable. It would be something alike UnboundLocalError when
> a local variable referenced before assignment. If they won't remove
> "else" completely in far future, that checking really worths
> implementing now.

Actually, I think a warning would be sufficient, as in the following
quick prototype. If someone can implement this quickly in CPython, that
would be great (last time I hacked it, it was 2.4)

Axy.

import ast

tree = ast.parse('''
# sample code
a = 0
for i in 'asd':
     a += i
     while x:
         pass
     else:
         print('wow')
     break
     print(i)
else:
     print(0)
''', mode='exec')

def check_ast(node):
     if isinstance(node, (ast.For, ast.AsyncFor, ast.While)):
         if node.orelse and have_no_break(node.body):
             print(f'Warning: the loop at line {node.lineno} has no
"break" statement,'
                   f' "else" clause at line {node.orelse[0].lineno}
won\'t run')
     else:
         for child in ast.iter_child_nodes(node):
             check_ast(child)

def have_no_break(loop_body):
     for node in loop_body:
         if isinstance(node, (ast.For, ast.AsyncFor, ast.While)):
             # nested loop
             check_ast(node)
         elif isinstance(node, ast.Break):
             return False
         elif isinstance(node, list):
             for child in ast.iter_child_nodes(node):
                 if have_no_break(child) == False:
                     return False
     return True


for node in tree.body:
     check_ast(node)
--
https://urldefense.com/v3/__https://mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mlK4jRkfDC_akw-fIqWaMVf707GQsiyvj_sRHTsFnuG4ak5mKWwSavtz4njlBNIu1H0VHrR9gyjuQpxGqZ1dacU1Xw$<https://urldefense.com/v3/__https:/mail.python.org/mailman/listinfo/python-list__;!!Cn_UX_p3!mlK4jRkfDC_akw-fIqWaMVf707GQsiyvj_sRHTsFnuG4ak5mKWwSavtz4njlBNIu1H0VHrR9gyjuQpxGqZ1dacU1Xw$>


More information about the Python-list mailing list