The docs simply aren't correct about the default values as you've pointed out. However, they're consistent other than that minor error. You can view the docs I am referring to here: https://docs.python.org/3/library/stdtypes.html#common-sequence-operations
Note that the behavior is definitionaly correct according to the docs:
The slice of s from i to j with step k is defined as the sequence of
items with index x = i + n*k such that 0 <= n < (j-i)/k. In other
words, the indices are i, i+k, i+2*k, i+3*k and so on, stopping when j
is reached (but never including j).
When you do:
>>> a = "hello"
>>> y = a[0:5:-1]
we have that i == 0
, j == 5
, and k == -1
. So we are grabbing items at index x = i + n*k
for n
starting at 0
and going up to (j-i)/k
. However, observe that (j-i)/k == (5-0)/-1 == -5
. There are no n
such that 0 <= n < -5
, so you get the empty string:
>>> y
''
Do a[start:stop][::step]
when in doubt (it's almost always what we want)
It's almost always the case that when you pass a negative step to something like x[start:stop:step]
, what you want to happen is for the sub selection to happen first, and then just go backwards by step
(i.e. we usually want x[start:stop][::step]
.
Futhermore, to add to the confusion, it happens to be the case that
x[start:stop:step] == x[start:stop][::step]
if step > 0
. For example:
>>> x = list(range(10))
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[2:6:2]
[2, 4]
>>> x[2:6][::2]
[2, 4]
>>> x[1:10][::3]
[1, 4, 7]
>>> x[1:10:3]
[1, 4, 7]
Unfortunately, this doesn't hold when step < 0
, even though it's tempting to think that it should.
After being burned by this a couple times, I realized it's just safer to always do the step clause after you perform the start:stop
slice. So I almost always start with y = x[start:stop][::step]
, at least when prototyping or creating a new module where correctness/readability is the primiary concern. This is less performant than doing a single slice, but if performance is an issue, then you can do the less readable:
y = x[start:stop:step] if step > 0 else x[stop:start:step]
HTH.