7

When slicing in python, omitting the end portion of the slice (ie the end in list[:end:]) results in end being defined as "the size of the string being sliced." *

However, this doesn't seem to hold true when using the step argument (the step in list[::step]) in a slice, at least when the step argument is -1. A simple example:

>>> l = [1, 2, 3]
>>> l[::-1]
[3, 2, 1]
>>> l[:len(l):-1]
[]

This indicates that in the case of a step argument being passed, an omitted end value is not equivalent to explicitly passing the size of the object being sliced.

Perhaps this is just a failure of mine reading the documentation, but I'd like to understand why my above example seems to contradict the Python documentation about omitting end values in slices, and ideally where this different is documented.


* Slice indices have useful defaults; an omitted first index defaults to zero, an omitted second index defaults to the size of the string being sliced.
Nolen Royalty
  • 18,415
  • 4
  • 40
  • 50
  • 3
    `l[len(l)::-1]` is `[3, 2, 1]`. The beginning is the end when you go backwards. – Dan D. Apr 28 '16 at 00:57
  • the stop is now set at the third index, when the string is reversed by the step -1 the stop is immediately reached. That is why it returns a empty list – Sven Hakvoort Apr 28 '16 at 01:03
  • 2
    The documentation excerpt is incorrect. It only applies when the step is positive. In fact, there is no integer value that corresponds to the default for the stop index when step is -1, since it would logically be -1, except that has a special meaning to Python. You have to use `None` to get the desired index. It's a flaw in the slice notation. – Tom Karzes Apr 28 '16 at 01:07

2 Answers2

6

The documentation you're referencing is the tutorial, which gives only an informal overview of Python syntax and semantics. It doesn't explain all the details. You'll note that the tutorial page you linked to doesn't even discuss negative indices.

The actual documentation is given in the library reference under sequence types. Although it is a bit terse and not easy to understand on a first read, it does clarify that for a slice [i:j:k]:

If i or j are omitted or None, they become “end” values (which end depends on the sign of k).

BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • perfect, this is exactly what I was looking for. I hadn't been able to find documentation explicitly explaining that `i` and `j` are flipped depending on the sign of `k`. I suppose asking an introductory tutorial for precise language is unreasonable, although unfortunately the tutorial is the only official documentation that comes up when you google "python slicing" – Nolen Royalty Apr 28 '16 at 01:09
  • It says they become "end values" depending on the sign of k. But what are these end values? What are the end values when k is positive and what are they when they are negative? – Asad Moosvi Aug 14 '17 at 20:00
  • @AsadMoosvi: That is explained in the same documentation: " 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)." It's just that the mapping of i/j to None/len(s) may switch if the step is negative. – BrenBarn Aug 15 '17 at 03:58
2

l[::-1] is the same thing as l.__getitem__(slice(None, None, -1)). Since the start and the stop are both None, the list will be traversed from one end to the other. The step argument determines the direction as well as the step.

zondo
  • 19,901
  • 8
  • 44
  • 83