Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Precedence of "in" in Python

Tags:

This is a bit of a (very basic) language-lawyer kind of question. I understand what the code does, and why, so please no elementary explanations.

In an expression, in has higher precedence than and. So if I write

if n in "seq1" and "something":     ... 

it is interpreted just like

if (n in "seq1") and "something":     ... 

However, the in of a for loop has lower precedence than and (in fact it has to, otherwise the following would be a syntax error). Hence if a Python beginner writes

for n in "seq1" and "something":     ... 

..., it is equivalent to this:

for n in ("seq1" and "something"):     ... 

(which, provided "seq1" is truthy, evaluates to for n in "something").

So, the question: Where is the precedence of the for-loop's in keyword specified/documented? I understand that n in ... is not an expression in this context (it does not have a value), but is part of the for statement's syntax. Still, I'm not sure how/where non-expression precedence is specified.

like image 320
alexis Avatar asked Nov 24 '15 15:11

alexis


People also ask

What is the precedence order in Python?

Answer: The correct order of precedence is given by PEMDAS which means Parenthesis (), Exponential **, Multiplication *, Division /, Addition +, Subtraction -.

What is the precedence of arithmetic operators in Python?

Python will always evaluate the arithmetic operators first (** is highest, then multiplication/division, then addition/subtraction).

Which is lowest order of precedence in Python?

The new Assignment expression (:=) operator from Python 3.8 onwards has the lowest precedence while parentheses() have the highest precedence.


1 Answers

In the context of a for statement, the in is just part of the grammar that makes up that compound statement, and so it is distinct from the operator in. The Python grammar specification defines a for statement like this:

for_stmt ::=  "for" target_list "in" expression_list ":" suite               ["else" ":" suite] 

The point to make is that this particular in will not be interpreted as part of target_list, because a comparison operation (e.g. x in [x]) is not a valid target. Referring to the grammar specification again, target_list and target are defined as follows:

target_list     ::=  target ("," target)* [","] target          ::=  identifier                      | "(" target_list ")"                      | "[" target_list "]"                      | attributeref                      | subscription                      | slicing                      | "*" target 

So the grammar ensures that the parser sees the first in token after a target_list as part of the for ... in ... statement, and not as a binary operator. This is why trying to write things very strange like for (x in [x]) in range(5): will raise a syntax error: Python's grammar does not permit comparisons like (x in [x]) to be targets.

Therefore for a statement such as for n in "seq1" and "something" is unambiguous. The target_list part is the identifier n and the expression_list part is the iterable that "seq1" and "something" evaluates to. As the linked documentation goes on to say, each item from the iterable is assigned to target_list in turn.

like image 185
Alex Riley Avatar answered Oct 13 '22 20:10

Alex Riley