Reputation: 51
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 to me, step by step, how the following line works?
>>> a[:0] = a[::2] = a[1::2] = a[:]
Upvotes: 3
Views: 232
Reputation: 15309
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
b = a[:]
makes a temp copy of aa[: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 worka[::2] = b
sets the values at even indices (i.e. every second index starting from the front)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[:])
Upvotes: 4