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://mail.python.org/mailman/listinfo/python-list

Reply via email to