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 :-(
...