Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mysterious interaction between Python's slice bounds and "stride"

I understand that given an iterable such as

>>> it = [1, 2, 3, 4, 5, 6, 7, 8, 9]

I can turn it into a list and slice off the ends at arbitrary points with, for example

>>> it[1:-2]
[2, 3, 4, 5, 6, 7]

or reverse it with

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

or combine the two with

>>> it[1:-2][::-1]
[7, 6, 5, 4, 3, 2]

However, trying to accomplish this in a single operation produces in some results that puzzle me:

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

Only after much trial and error, do I get what I'm looking for:

>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]

This makes my head hurt (and can't help readers of my code):

>>> it[-3:0:-1] == it[1:-2][::-1]
True

How can I make sense of this? Should I even be pondering such things?


FWYW, my code does a lot of truncating, reversing, and listifying of iterables, and I was looking for something that was faster and clearer (yes, don't laugh) than list(reversed(it[1:-2])).

like image 904
orome Avatar asked Oct 26 '15 17:10

orome


People also ask

What is the relationship between indexing and slicing in Python?

“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.

What is stride in slicing strings in Python?

String slicing can also accept a third parameter, the stride , which refers to how many characters you want to move forward after the first character is retrieved from the string. The value of stride is set to 1 by default.

Is Python slicing inclusive or exclusive?

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.

What is the concept of slicing in Python?

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

This is because in a slice like -

list[start:stop:step]

start is inclusive, resultant list starts at index start.

stop is exclusive, that is the resultant list only contains elements till stop - 1 (and not the element at stop).

So for your caseit[1:-2] - the 1 is inclusive , that means the slice result starts at index 1 , whereas the -2 is exclusive , hence the last element of the slice index would be from index -3.

Hence, if you want the reversed of that, you would have to do it[-3:0:-1] - only then -3 would be included in the sliced result, and the sliced result would go upto 1 index.

like image 133
Anand S Kumar Avatar answered Oct 25 '22 10:10

Anand S Kumar


The important things to understand in your slices are

  • Start will be included in the slice

  • Stop will NOT be included in the slice

  • If you want to slice backwards, the step value should be a negative value.

Basically the range which you specify is a half-open (half-closed) range.


When you say it[-3:0:-1] you are actually starting from the third element from the back, till we reach 0 (not including zero), step one element at a time backwards.

>>> it[-3:0:-1]
[7, 6, 5, 4, 3, 2]

Instead, you can realize the start value like this

>>> it[len(it)-3 : 0 : -1]
[7, 6, 5, 4, 3, 2]
like image 42
thefourtheye Avatar answered Oct 25 '22 08:10

thefourtheye