2

I was reading a post called "Duplicate each member in a list". I found an answer to solve this problem that I can't understand :

>>> a = [3, 1, 4, 1, 5]
>>> a[:0] = a[::2] = a[1::2] = a[:]
>>> a
[3, 3, 1, 1, 4, 4, 1, 1, 5, 5]

Could you explain me step by step how works the following line of program :

>>> a[:0] = a[::2] = a[1::2] = a[:]
SaukratesK
  • 41
  • 3
  • 1
    I think that [this](https://stackoverflow.com/questions/48633951/why-does-chained-assignment-work-this-way) might solve your doubt – lolloz98 Apr 24 '21 at 08:59

1 Answers1

3

The key here is understanding that the sequence is executed left-to-right, all with reference to the rightmost value.

The rightmost slice a[:] gets assigned to each of the 3 leftmost slices. Note the use of a[:] instead of a, this ensures we make one copy at the beginning and our operations on a don't change this value. A clearer way to write this would be to store the copy a[:]:

>>> a = [3, 1, 4, 1, 5]
>>> b = a[:]
>>> b
[3, 1, 4, 1, 5]

>>> a[:0] = b
>>> a
[3, 1, 4, 1, 5, 3, 1, 4, 1, 5]
#^^^^^^^^^^^^^ changed

>>> a[::2] = b
>>> a
[3, 1, 1, 1, 4, 3, 1, 4, 5, 5]
#^     ^     ^     ^     ^ changed 

>>> a[1::2] = b
>>> a
[3, 3, 1, 1, 4, 4, 1, 1, 5, 5]
#   ^     ^     ^     ^     ^ changed

Let us discuss the individual steps

  1. b = a[:] makes a temp copy of a
  2. a[:0] = b inserts b at the front, but is actually just used for padding a to twice the length, so that the next two statements work
  3. a[::2] = b sets the values at even indices (i.e. every second index starting from the front)
  4. a[1::2] = b sets the values at odd indices (i.e. every second index excluding the front)

Another way to get the same result is the following tuple assignment, which also evaluates the right-hand-side first, and then the left-hand-side from left-to-right:

(a[:0], a[::2], a[1::2]) = (a[:], a[:], a[:])
xjcl
  • 12,848
  • 6
  • 67
  • 89