By user3105173


2019-12-02 22:18:25 8 Comments

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?

3 comments

@sammy 2019-12-02 22:28:18

This behavior is explained in the documentation.

The slice of s from i to j is defined as the sequence of items with index k such that i <= k < j. If i or j is greater than len(s), use len(s). If i is omitted or None, use 0. If j is omitted or None, use len(s). If i is greater than or equal to j, the slice is empty.

The slice of s from i to j with step k.... stopping when j is reached (but never including j). When k is positive, i and j are reduced to len(s) if they are greater. When k is negative, i and j are reduced to len(s) - 1 if they are greater. If i or j are omitted or None, they become “end” values (which end depends on the sign of k).

@Carcigenicate 2019-12-02 22:21:59

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.

@Jean-François Fabre 2019-12-02 22:23:54

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)

@user3105173 2019-12-02 22:27:48

Why would python set the start to "end of list" when doing a[:5:-1]?? Shouldn't it be "start of list"?

@Jean-François Fabre 2019-12-02 22:28:48

since the step is negative, default start & stop are reversed. Else [::-1] notation would not work at all.

@juanpa.arrivillaga 2019-12-02 23:16:34

@user3105173 because, slice notation is for convenience. When the steps are reversed, the implied starts-end change accordingly

Related Questions

Sponsored Content

23 Answered Questions

[SOLVED] Does Python have a ternary conditional operator?

16 Answered Questions

[SOLVED] What are metaclasses in Python?

63 Answered Questions

[SOLVED] Calling an external command from Python

26 Answered Questions

[SOLVED] How do I concatenate two lists in Python?

36 Answered Questions

[SOLVED] How to get the current time in Python

  • 2009-01-06 04:54:23
  • user46646
  • 3093616 View
  • 2644 Score
  • 36 Answer
  • Tags:   python datetime time

10 Answered Questions

[SOLVED] Does Python have a string 'contains' substring method?

32 Answered Questions

[SOLVED] Understanding slice notation

29 Answered Questions

[SOLVED] Finding the index of an item given a list containing it in Python

  • 2008-10-07 01:39:38
  • Eugene M
  • 3542674 View
  • 2905 Score
  • 29 Answer
  • Tags:   python list indexing

22 Answered Questions

[SOLVED] JavaScript chop/slice/trim off last character in string

31 Answered Questions

[SOLVED] "Least Astonishment" and the Mutable Default Argument

Sponsored Content