[Python-ideas] Where did we go wrong with negative stride?

Steven D'Aprano steve at pearwood.info
Fri Nov 1 11:17:52 CET 2013


On Thu, Oct 31, 2013 at 03:37:36PM +0200, אלעזר wrote:

> Perhaps we can get this End object by adding two tokens: ":-" and "[-". So
> 
> a[-3:-5] == a[slice(End-3, End-5, None)]

That's ambiguous. Consider:

a[-2]

Is that a dict lookup with key -2, or a list indexed with End-2? Or 
worse, a dict lookup with key len(a)-2.

To break the ambiguity, we'd need a rule that End objects can only occur 
inside slices with at least one colon. But, I think that means that the 
parser would have to look ahead to see whether it was within a slice or 
not, and that might not be possible with Python's parser. Even if were, 
it's still a special case that -2 means something different inside a 
slice than outside a slice, and we know what the Zen of Python says 
about special cases.


> although it will turn a[-3] into a[End-3]. I don't think it's a
> problem if the latter will behave in the same way as the former (i.e
> End-3 be a subtype of int).

So what would (End-3)*10 return? How about End & 0xF ?

 
> Note that with an End object (regardless of wheather it's called
> "End", "len-x" or ":-x") we can get End/5. I think that's a nice thing
> to have.

I presume that you expect a[End/5] to be equivalent to a[len(a)//5] ?


> One more thing: End-5 should be callable, so it can be passed around.
> 
> (End-3)("hello") == len("hello")-3
> (End-0)("hello") == len("hello")
> 
> This way End is a generalization of len, making len somewhat redundant.

All this seems very clever, but as far as I'm concerned, it's too 
clever. I don't like objects which are context-sensitive. Given:

    x = End-2

then in this context, x behaves like 4:

    "abcdef"[x:]

while in this context, x behaves like 0:

    "abcd"[x:]

I really don't like that. That makes it hard to reason about code.

End seems to me to be an extremely sophisticated object, far too 
sophisticated for slicing, which really ought to be conceptually and 
practically a simple operation. I would not have to like to explain this 
to beginners to Python. I especially would not like to explain how it 
works. (How would it work?) I think the only answer is, "It's magic". I 
think it is something that would be right at home in PHP or Perl, and I 
don't mean that as an insult, but only that it's not a good fit to 
Python.


-- 
Steven


More information about the Python-ideas mailing list