Following up my previous question I have the following one. Are these the same in Python?
a += b[1] / 2
and
a += (b[1] / 2)
Providing that:
a
has already been defined earlier as floatb
is a list of tuplesb[1]
is a tuple with a single elementSimilarly I would be interested to learn as well the behavior if:
a
has already been defined earlier as floatb
is a list of floatsThe rules of how Python parses expressions are defined in the Python grammar. Note that the types are irrelevant. In fact Python is dynamically types, so that means that at the time an expression is parsed and analyzed, the types of the variables is unknown. In fact a variable have different values (with different types) through the process, and a line can be evaluated multiple times, with the variables each time carrying a value of a different type.
If we take a look at the grammar, we see:
expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'@'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom_expr ['**' factor] atom_expr: ['await'] atom trailer* atom: ('(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') testlist_comp: (test|star_expr) ( comp_for | (',' (test|star_expr))* [','] ) trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
The "subscription" (the [1]
in b[1]
is thus defined in a production rule of trailer
, and if we look at the grammar, this can only be the product of a factor
, so that means that the /
operator takes precedence over the subscription.
So that means that:
a += b[1] / 2
is equivalent to:
a += ((b[1]) / 2)
Note that since Python is dynamically typed, the parsing (and analyzing) step will not give any guarantees that the expression is sensical. For example a tuple can not be devided by two. So this will result in a TypeError
:
>>> (2.0, 4.0) / 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for /: 'tuple' and 'int'
For a numpy
array however, this makes sense:
>>> from numpy import array
>>> array([2.0, 4.0])/2
array([1., 2.])