1

I ran into a weird behavior trying to swap elements of an array.

Initial State

i = 1
nums = [0, 1]

What didn't worked

nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i]
print(nums) # [0, 1]

What worked

nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1]
print(nums) # [1, 0]

I believed both expressions should have had the same outcome as the right-side of assignment is evaluated first.

Tested on Python 2.7.16 and Python 3.7.6 on macOS Catalina, 10.15.4.

Note: nums[1], nums[0] = nums[0], nums[1] and nums[0], nums[1] = nums[1], nums[0] work just as expected.

  • Why don't you just swap like this? 'nums[i], nums[i-1] = nums[i-1], nums[i]' – Mace Apr 24 '20 at 18:41
  • @Mace This is just an example. The elements to be swapped might be anywhere in the array. I was using this as part of cycle sorting. – Arsalan Jumani Apr 25 '20 at 06:55
  • I understand. Thanks. – Mace Apr 25 '20 at 06:57
  • Does this answer your question? [Understand Python swapping: why is a, b = b, a not always equivalent to b, a = a, b?](https://stackoverflow.com/questions/68152730/understand-python-swapping-why-is-a-b-b-a-not-always-equivalent-to-b-a-a) – cigien Jun 30 '21 at 18:06

1 Answers1

2

This is because the arguments on the left hand side of the assignment, are still evaluated left-to-right. Let's break down the non-working example:

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

becomes

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

becomes

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

now the left hand side is evaluated, but nums[i] is evaluated first. This makes nums[1] into 0.

Now if we evaluate nums[nums[i] - 1], we see that this evaluates to nums[0 - 1], which is nums[-1], which is nums[1].

So this entire expression does nothing. It simply sets nums[1] to 0, and then back to 1.

cigien
  • 57,834
  • 11
  • 73
  • 112