5

I'm struggling with this strange behaviour in Python (2 and 3):

>>> a = [1, 2]
>>> a[a.index(1)], a[a.index(2)] = 2, 1

This results in:

>>> a
[1, 2]

But if you write

>>> a = [1, 2]
>>> a[a.index(1)], a[a.index(2)] = x, y

where x, y != 2, 1 (can be 1, 1, 2, 2 , 3, 5, etc.), this results in:

>>> a == [x, y]
True

As one would expect. Why doesn't a[a.index(1)], a[a.index(2)] = 2, 1 produce the result a == [2, 1]?

>>> a == [2, 1]
False
Peter Wood
  • 23,859
  • 5
  • 60
  • 99
Dargor
  • 623
  • 1
  • 4
  • 12

1 Answers1

10

Because it actually gets interpreted like this:

>>> a = [1, 2]
>>> a
[1, 2]
>>> a[a.index(1)] = 2
>>> a
[2, 2]
>>> a[a.index(2)] = 1
>>> a
[1, 2]

To quote, per the standard rules for assignment (emphasis mine):

  • If the target list is a comma-separated list of targets: 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.

The assignment to a[a.index(1)] (i.e. a[0]) happens before the second assignment asks for a.index(2), by which time a.index(2) == 0.

You will see the same behaviour for any assignment:

foo = [a, b]
foo[foo.index(a)], foo[foo.index(b)] = x, y

where x == b (in this case, any assignment where the first value on the right-hand side is 2).

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
  • 1
    Can you reference the assignment order in Python from the docs? – Dargor Nov 03 '15 at 13:49
  • Upvoted and accepted. Thank you for your great work! – Dargor Nov 03 '15 at 13:53
  • Why does ``a = 1; a, b = 2, a`` result in ``b == 1`` then? You might want to discuss the differences between mutable and immutable objects in your answer. – pzp Nov 03 '15 at 14:03
  • 1
    @pzp that's not mutable vs. immutable, that's because the right-hand side is fully evaluated before any of the assignments begin. The same thing would happen with a mutable `a`. – jonrsharpe Nov 03 '15 at 14:20