Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavior with python slicing [duplicate]

Tags:

python

list

slice

Suppose we have this list:

>>> a = [x for x in range(10)]
>>> print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Separately, both ways to slice work as expected:

>>> a[3:8]
[3, 4, 5, 6, 7]

>>> a[::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

But, when combined:

>>> a[3:8:-1]
[]

I would expect it to be [7, 6, 5 ,4, 3] or perhaps [6, 5, 4, 3, 2] (if reversing happened first). It is also interesting to consider what happens when either start or stop parameters are not passed:

>>> a[:5:-1]
[9, 8, 7, 6]

This is almost what I would expect, only its one item short. Tested this with numpy and it seems to behave in the same way.

Whats going on here?

like image 621
user3105173 Avatar asked Dec 02 '19 22:12

user3105173


People also ask

Does Python list slicing make a copy?

Slicing lists does not generate copies of the objects in the list; it just copies the references to them. That is the answer to the question as asked.

Is Python slicing inclusive?

Python is a zero-indexed language (things start counting from zero), and is also left inclusive, right exclusive you are when specifying a range of values. This applies to objects like lists and Series , where the first element has a position (index) of 0.

What does slicing in Python do?

Definition and Usage The slice() function returns a slice object. A slice object is used to specify how to slice a sequence. You can specify where to start the slicing, and where to end. You can also specify the step, which allows you to e.g. slice only every other item.


2 Answers

With

a[3:8:-1]

The start and stop positions of the slice aren't adjusted based on the step. With a negative step, you're having it go backwards from 3, but there are no elements with indices in the range 3 to 8 counting back from 3, so you get an empty list.

You need to set the start and stop accordingly:

a[8:3:-1]

Which will count back from 8 to 4.

like image 173
Carcigenicate Avatar answered Oct 17 '22 08:10

Carcigenicate


a[3:8:-1] instructs python to start from 3 and go to 8 by steps of -1

This creates an empty list: it's not possible to reach 8 from 3 by adding -1 (just like list(range(3,8,-1)) which gives an empty list too)

When you do a[:5:-1] then start is the default start, which python sets to "end of list" so it "works"

Same as when you do a[::-1] the start & stop are the default ones, and python understands that they're from end to start (else this notation wouldn't be useable)

like image 22
Jean-François Fabre Avatar answered Oct 17 '22 09:10

Jean-François Fabre