Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange slicing behavior in Python

I found this to be a bit strange. Can anyone explain to me: Why, if I have a list like this:

l = [1, 2, 3, 4, 5]

and I do this reassignment:

l[-1:0] = [99,]

then it inserts the 99 to the left of the 5, like so:

[1, 2, 3, 4, 99, 5]

We must assign to an iterable [99,], assigning to just the integer 99 will give an error, which might be a clue as to what's happening here... I guess?

like image 981
mrwonderfulness Avatar asked May 11 '26 05:05

mrwonderfulness


2 Answers

According to the official Docs:

In the table s is an instance of a mutable sequence type, t is any iterable object and x is an arbitrary object that meets any type and value restrictions imposed by s

enter image description here

Note (1): t must have the same length as the slice it is replacing.

So, if you do l[-1] = 99, you are replacing the item in position -1 (that means, one less than the last) to the value 99.

On the other hand, if you do l[-1:0] = [99,], you taking the elements from index -1 to 0 (that means, a slice of length zero in the position -1), and replacing those by the elements of [99,] (that is why it must be an iterable), which effectively is a semantic insert.

like image 175
Rodrigo Rodrigues Avatar answered May 13 '26 19:05

Rodrigo Rodrigues


When you slice a Python list with [start:end] you end up with another list. The beginning of the new list in your example is the location of the last element in your original list. Just because the value of l[-1:0] in your example is [] it does not mean that this is simply an empty list. Its value is an empty list, but the reference to l[-1:0] is to a sliced list within an existing list.

So in your example

l = [1,2,3,4,5]
#            ^       l[-1:0] starts here but the size is 0

When you assign a list to a sliced position of another list, you are effectively performing list concatenation. This is the equivalent of what you are doing.

l=[1,2,3,4,5]
l[4:0] = [99] # concatenate a new list at the position of the final element in the original list

# A different way to look at it
l[0:4] + [99] + l[4:]

The result again is effectively concatenating the two lists. More specifically, you are inserting the elements of a new list into the original at the position you've indicated. Using a literal integer such as 99 will result in an error because you cannot concatenate an int and a list directly. However, as others have pointed out, a slice assignment can use any iterable, so l[-1,0] = (99,) works by the same principle.

like image 29
h0r53 Avatar answered May 13 '26 18:05

h0r53



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!