How does assignment work with list slices?

PythonListSlice

Python Problem Overview


Python docs says that slicing a list returns a new list.
Now if a "new" list is being returned I've the following questions related to "Assignment to slices"

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

Now the output would be:

[4, 5, 3] 
  1. How can something that is returning something come on the left side of expression?
  2. Yes, I read the docs and it says it is possible, now since slicing a list returns a "new" list, why is the original list being modified? I am not able to understand the mechanics behind it.

Python Solutions


Solution 1 - Python

You are confusing two distinct operation that use very similar syntax:

1) slicing:

b = a[0:2]

This makes a copy of the slice of a and assigns it to b.

2) slice assignment:

a[0:2] = b

This replaces the slice of a with the contents of b.

Although the syntax is similar (I imagine by design!), these are two different operations.

Solution 2 - Python

When you specify a on the left side of the = operator, you are using Python's normal assignment, which changes the name a in the current context to point to the new value. This does not change the previous value to which a was pointing.

By specifying a[0:2] on the left side of the = operator, you are telling Python you want to use slice assignment. Slice assignment is a special syntax for lists, where you can insert, delete, or replace contents from a list:

Insertion:

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

Deletion:

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

Replacement:

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

Note:

> The length of the slice may be different from the length of the > assigned sequence, thus changing the length of the target sequence, if > the target sequence allows it. - source

Slice assignment provides similar function to tuple unpacking. For example, a[0:1] = [4, 5] is equivalent to:

# Tuple Unpacking
a[0], a[1] = [4, 5]

With tuple unpacking, you can modify non-sequential lists:

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

However, tuple unpacking is limited to replacement, as you cannot insert or remove elements.

Before and after all these operations, a is the same exact list. Python simply provides nice syntactic sugar to modify a list in-place.

Solution 3 - Python

I came across the same question before and it's related to the language specification. According to assignment-statements,

  1. If the left side of assignment is subscription, Python will call __setitem__ on that object. a[i] = x is equivalent to a.__setitem__(i, x).

  2. If the left side of assignment is slice, Python will also call __setitem__, but with different arguments: a[1:4]=[1,2,3] is equivalent to a.__setitem__(slice(1,4,None), [1,2,3])

That's why list slice on the left side of '=' behaves differently.

Solution 4 - Python

By slicing on the left hand side of an assignment operation, you are specifying which items to assign to.

Solution 5 - Python

When you did a[0:2] = [4,5], you assigned the the left hand side of the = (the slice a[0:2]) the value on the right side of the =, [4,5].

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKartik AnandView Question on Stackoverflow
Solution 1 - PythonNPEView Answer on Stackoverflow
Solution 2 - PythonCasey KuballView Answer on Stackoverflow
Solution 3 - PythonStanView Answer on Stackoverflow
Solution 4 - PythonfraxelView Answer on Stackoverflow
Solution 5 - Pythonthing10View Answer on Stackoverflow