Operator associativity

I understand why the following does not worK

j * (j :=3)

because (I thought) * has left-to-right associativity. But I was surprised that the following did not work


I figured since ** has right-to-left associativity that the j:=3 would be evaluated first (settingj to 3) and then the expression would return 27. However, I got the same answer as in the multiplication example - j not defined. Why doesn’t the above exponeniation expression work?

Expressions are evaluated left-to-right. The associativity doesn’t matter.

I will assume you are typing this at the interactive prompt? It surely works with a function with j as a parameter.

I think the associativity is not relevant here. If you look at the bytecode, you can see that before applying the operator (or sequence of operators), first the variables are loaded, left to right in order. So if your first variable happens to be not yet defined, you will get an error, and it it’s already defined, you may be using two different values.

>>> import dis
>>> dis.dis("a**(a:=4)")
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (a)
              4 LOAD_CONST               0 (4)
              6 COPY                     1
              8 STORE_NAME               0 (a)
             10 BINARY_OP                8 (**)
             14 RETURN_VALUE
>>> dis.dis("a**(b:=2)**c")
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (a)
              4 LOAD_CONST               0 (2)
              6 COPY                     1
              8 STORE_NAME               1 (b)
             10 LOAD_NAME                2 (c)
             12 BINARY_OP                8 (**)
             16 BINARY_OP                8 (**)
             20 RETURN_VALUE

So if the first variable ‘a’ is already defined, then the expression a**(a:=a+1) will have the same effect as a**(a+1); a = a + 1

The walrus operator is allowed in that expression, but it seems kind of bad style to use it like that (modifying a variable name that is already being used earlier in the expression), similar in a way to modifying a container while iterating over it (also allowed…)

1 Like

Makes no sense to talk about associativity when you only have one **. You need at least two for that, e.g., a ** b ** c evaluates the right ** before the left one.