Search code examples
pythonparallel-assignment

Python Parallel Assignments


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.


Solution

  • 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.