pythontensorflowoperator-precedenceaugmented-assignment

Python operator precedence with augmented assignment including sequence


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:

Similarly I would be interested to learn as well the behavior if:


Solution

  • The 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.])