[Python-ideas] Where did we go wrong with negative stride?
Guido van Rossum
guido at python.org
Sun Oct 27 21:44:50 CET 2013
On Sun, Oct 27, 2013 at 11:38 AM, Tim Peters <tim.peters at gmail.com> wrote:
> I may have a different slant on this.
Hardly -- I agree with everything you say here. :-)
> 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.
>
Yup.
>
> <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'
>
Right, that's the point of my post.
>
> 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).
>
Except reversed() returns an iterator. But yes.
This would also make a[i:j:k] == a[i:j][::k].
If I could do it over I would do it this way.
>
> 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.
>
Which probably would cause more backward incompatibility bugs, since by now
many people have figured out that if you want [4, 3, 2, 1, 0] you have to
write range(4, -1, -1). :-(
>
>
> [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 ;-)
>
Yup, MRAB pointed this out too.
>
> >...
> > Are we stuck with this forever?
>
> Probably :-(
>
Sadly, I agree. If we wanted to change this in Python 4, we'd probably have
to start deprecating range() with negative stride today to force people to
replace their uses of that with reversed(range(...)).
--
--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20131027/2bd8b047/attachment.html>
More information about the Python-ideas
mailing list