[Python-ideas] Where did we go wrong with negative stride?
Tim Peters
tim.peters at gmail.com
Sun Oct 27 19:38:05 CET 2013
I may have a different slant on this. I've found that - by far - the
most successful way to "teach slices" to newcomers is to invite them
to view indices as being _between_ sequence elements.
<position 0> <element> <position 1> <element> <position 2> <element>
<position 3> ...
Then i:j selects the elements between position i and position j.
>>> "abcde"[2:4]
'cd'
But for negative strides this is all screwed up ;-)
>>> "abcde"[4:2:-1]
'ed'
They're not getting the elements between "positions" 2 and 4 then,
they're getting the elements between positions 3 and 5. Why?
"Because that's how it works" - they have to switch from thinking
about positions to thinking about array indexing.
So I would prefer that the i:j in s[i:j:k] _always_ specify the
positions in play:
If i < 0:
i += len(s) # same as now
if j < 0:
j += len(s) # same as now
if i >= j:
the slice is empty! # this is different - the sign of k is irrelevant
else:
the slice indices selected will be
i, i + abs(k), i + 2*abs(k), ...
up to but not including j
if k is negative, this index sequence will be taken in reverse order
Then "abcde"[4:2:-1} would be "", while "abcde"[2:4:-1] would be "dc",
the reverse of "abcde"[2:4]. And s[0:len(s):-1] would be the same as
reversed(s).
So it's always a semi-open range, inclusive "at the left" and
exclusive "at the right". But that's more a detail: the _point_ is
to preserve the mental model of selecting the elements "between
position". Of course I'd change range() similarly.
[Guido]
> For example,
>
> "abcde"[::-1] == "edcba"
>
> as you'd expect, but there is no number you can put as the second bound to
> get the same result:
Actually, any integer <= -1-len("abcde") = --6 works. But, yes,
that's bizarre ;-)
>...
> Are we stuck with this forever?
Probably :-(
> ...
More information about the Python-ideas
mailing list