While I thought I understood parallel assignments in Python, I now realize I am unsure. Moreover, for a long time, I saw the parallel assignment paradigm in the following way:
lst = [1, 2, 3, 4, 5]
# Switch index 1 with index 3
lst[1], lst[3] = lst[3], lst[1]
# Resulting output
# [1, 4, 3, 2, 5]
In the example above, since the right-hand side of the assignment statement is evaluated first, the values from the original ordering of the list are preserved; that is, lst[3]
represents the value 4
and lst[1]
represents the value 2
on the right-hand side of the statement. At the same time, the left-hand side of the assignment statement represents the locations to assign these respective values. So, the value of 4
will be assigned to the index location of 1
and the value of 2
will be assigned to the index location of 3
.
While this makes sense, I came across an obscure example:
lst = [1, 2, 3, 4, 5]
index = 1
A = index
B = lst[index] + 1
# Switch index A (1) with index B (3)
lst[A], lst[B] = lst[B], lst[A]
# Resulting output
# [1, 4, 3, 2, 5]
This snippet above works as it is expected to. However, if I slightly alter the code....
lst = [1, 2, 3, 4, 5]
index = 1
lst[index], lst[lst[index] + 1] = lst[lst[index] + 1], lst[index]
# Resulting Output
# Error
This snippet will result in an IndexError
. Can anyone break down what exactly is occurring here regarding the assignments? Based on my prior exposure to parallel assignments, I would expect the right-hand side of the assignment statement to evaluate to 4
and 2
, just as it had from the previous examples. Then, from there, I would think that lst[index]
represents the original location of 2
and lst[index] + 1
represents the original location of 4
. Therefore, the parallel assignment should work as expected, flipping the two values as it did in the previous instances.
The two indices on the left are not precomputed before the first assignment takes place. The entire assignment
lst[index], lst[lst[index] + 1] = lst[lst[index] + 1], lst[index]
behaves like
i1 = lst[index] + 1
lst[index] = lst[li]
i2 = lst[index] + 1
lst[i2] = lsp[index]
The assignment on line two changes what value i2
receives, in this case a value that doesn't correspond to a valid list index.