for -- else: what was the motivation?

Axy axy at declassed.art
Mon Oct 10 13:08:39 EDT 2022


> 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)


More information about the Python-list mailing list