Home > front end >  Strange slicing behavior in Python
Strange slicing behavior in Python

Time:08-20

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?

CodePudding user response:

According to the 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.

CodePudding user response:

First, you'll need to know how the slicing works fully. You can have 3 values: [start:end:step]

In your code, l[-1:0], using -1 as the start value will aim at the last value in the list, but it'll also try and find a list of values because of the end value being set. This is why you had to use a list to change the value.

To solve this issue, use l[-1] = 99 to change the last value of the list to 99 (assuming that's the intended result)

CodePudding user response:

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. It's an empty range at an existing list location.

So in your example

l = [1,2,3,4,5]
#            ^       l[-1:0] starts here but the range is effectively 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.

  • Related