Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is this list expanded with the slicing assignment? [duplicate]

Tags:

python

I came across the following code (sort of):

my_list = [1, [2, 3, 4], 5]
my_list[1:2] = my_list[1]

After running these two lines, the variable my_list will be [1, 2, 3, 4, 5]. Pretty useful for expanding nested lists.

But why does it actually do what it does?

I would have assumed that the statement my_list[1:2] = my_list[1] would do one of the following:

  • simply put [2, 3, 4] into the second position in the list (where it already is)
  • give some kind of "too many values to unpack" error, from trying to put three values (namely 2,3,4) into a container of only length 1 (namely my_list[1:2]). (Repeating the above with a Numpy array instead of a list results in a similar error.)

Other questions (e.g. How assignment works with python list slice) tend to not pay much attention to the discrepancy between the size of the slice to be replaced, and the size of the items you're replacing it with. (Let alone explaining why it works the way it does.)

like image 449
acdr Avatar asked Dec 29 '17 12:12

acdr


People also ask

Does slicing a list create a copy?

No, slicing returns a list which is inside the original list. Not a copied list.

What is slice assignment in Python?

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]

Does slicing array create a new list?

In short, slicing is a flexible tool to build new lists out of an existing list. Python supports slice notation for any sequential data type like lists, strings, tuples, bytes, bytearrays, and ranges. Also, any new data structure can add its support as well.

What is difference between slicing and indexing of list?

“Indexing” means referring to an element of an iterable by its position within the iterable. “Slicing” means getting a subset of elements from an iterable based on their indices.


2 Answers

Slice assignment replaces the specified part of the list with the iterable on the right-hand side, which may have a different length than the slice. Taking the question at face value, the reason why this is so is because it's convenient.

You are not really assigning to the slice, i.e. Python doesn't produce a slice object that contains the specified values from the list and then changes these values. One reason that wouldn't work is that slicing returns a new list, so this operation wouldn't change the original list.

Also see this question, which emphasizes that slicing and slice assignment are totally different.

like image 51
nnnmmm Avatar answered Oct 25 '22 19:10

nnnmmm


Here is the relevant bit from the Python Language Reference

If the target is a slicing: The primary expression in the reference is evaluated. It should yield a mutable sequence object (such as a list). The assigned object should be a sequence object of the same type. Next, the lower and upper bound expressions are evaluated, insofar they are present; defaults are zero and the sequence’s length. The bounds should evaluate to integers. If either bound is negative, the sequence’s length is added to it. The resulting bounds are clipped to lie between zero and the sequence’s length, inclusive. Finally, the sequence object is asked to replace the slice with the items of the assigned sequence. 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.

This behavior makes sense qualitatively because when you slice a list you get a sub list so replacing that with another list shouldn't add a level of nesting. Allowing it to change the length of the list is a design choice. Other choices are possible as your numpy example demonstrates.

like image 36
Paul Panzer Avatar answered Oct 25 '22 19:10

Paul Panzer