Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understand Python swapping: why is a, b = b, a not always equivalent to b, a = a, b?

As we all know, the pythonic way to swap the values of two items a and b is

a, b = b, a

and it should be equivalent to

b, a = a, b

However, today when I was working on some code, I accidentally found that the following two swaps give different results:

nums = [1, 2, 4, 3]
i = 2
nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
print(nums)
# [1, 2, 4, 3]

nums = [1, 2, 4, 3]
i = 2
nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]
print(nums)
# [1, 2, 3, 4]

This is mind-boggling to me. Can someone explain to me what happened here? I thought in a Python swap the two assignments happen simultaneously and independently.

like image 929
Shaun Han Avatar asked Oct 10 '22 22:10

Shaun Han


People also ask

What does swapping mean in Python?

Python: swapping two variables Swapping two variables refers to mutually exchanging the values of the variables. Generally, this is done with the data in memory. The simplest method to swap two variables is to use a third temporary variable : define swap(a, b) temp := a a := b b := temp.

Is there a swap method in Python?

In Python, you can easily swap values without temp (temporary variable). It is possible to swap values of variables and to swap values (elements) in a list.


1 Answers

From python.org

Assignment of an object to a target list, optionally enclosed in parentheses or square brackets, is recursively defined as follows.

...

  • Else: The object must be an iterable with the same number of items as there are targets in the target list, and the items are assigned, from left to right, to the corresponding targets.

So I interpret that to mean that your assignment

nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]

is roughly equivalent to

tmp = nums[nums[i]-1], nums[i]
nums[i] = tmp[0]
nums[nums[i] - 1] = tmp[1]

(with better error-checking, of course)

whereas the other

nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]

is like

tmp = nums[i], nums[nums[i]-1]
nums[nums[i] - 1] = tmp[0]
nums[i] = tmp[1]

So the right-hand side is evaluated first in both cases. But then the two pieces of the left-hand side are evaluated in order, and the assignments are done immediately after evaluation. Crucially, this means that the second term on the left-hand side is only evaluated after the first assignment is already done. So if you update nums[i] first, then the nums[nums[i] - 1] refers to a different index than if you update nums[i] second.

like image 139
Silvio Mayolo Avatar answered Oct 18 '22 21:10

Silvio Mayolo