In the full python grammar specification with statement is defined as:
with_stmt: 'with' with_item (',' with_item)*  ':' suite
with_item: test ['as' expr]
Where expr is:
expr: xor_expr ('|' xor_expr)*
xor_expr: and_expr ('^' and_expr)*
and_expr: shift_expr ('&' shift_expr)*
Why does with_item contains expr rule instead of plain name?
This is valid python code:
with open('/dev/null') as f:
    pass
According to the grammar this code is also valid?
with open('/dev/null') as x^y|z:
    pass
                with open('/dev/null') as x^y|z:
    pass
Yes, this code is valid according to the grammar! Otherwise you'd get a parse error ("invalid syntax"). The parser proper is fine with this syntax, it's another part of the compiler that checks that such expression is not allowed on the left side (because as is semantically equivalent to the assignment). The reason why the grammar allows expr here, and not just NAME is that you can have any lvalue after as:
with open('/dev/null') as some.thing
with open('/dev/null') as some[thing] 
but there's no separate rule for lvalues, e.g. assignments use testlist on the left, which is even wider than expr.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With