
Given
a = [1, 2, 3, 4]
because
a[-2] -3
I expected that a.insert(-2, 0) would yield [1, 2, 0, 3, 4]. It was a rude shock to discover that
a [0, 1, 2, 3, 4]
In fact I think this may be the nastiest surprise Python has handed me since I started using it. The reference manual says "same as s[i:i] = [x] if i >= 0" which of course doesn't cover the i < 0 case. David Beasley's reference says "Inserts x at index i" which sounds like the behavior I was expecting but didn't get. Is this a deliberate design choice, an oversight, or a plain bug? If it's a choice, it's damn poorly documented -- this deserves at least a footnote in the list methods table. If it's an oversight or bug, I volunteer to fix it. -- <a href="http://www.tuxedo.org/~esr/">Eric S. Raymond</a> "America is at that awkward stage. It's too late to work within the system, but too early to shoot the bastards." -- Claire Wolfe

[Eric S. Raymond]
I never noticed it, but agree it's strange. Did you open a feature request on SourceForge? Note that array objects (created by the array module) share this behavior.
The reference manual says "same as s[i:i] = [x] if i >= 0" which of course doesn't cover the i < 0 case.
Which formally means its behavior is undefined.
David Beasley's reference says "Inserts x at index i" which sounds like the behavior I was expecting but didn't get.
Ya, so file a bug report with David <wink>.
Only Guido *may* be able to say for sure. Plausible: the behavior for i<0 was deliberate at the start, and when Python *grew* negative indices (it didn't always accept them), fear of incompatibility prevented changing .insert behavior (in the other cases where negative indices "grew a meaning", the old behavior was to raise an exception; but .insert accepted them silently). Digging thru CVS, the current behavior for i<0 has always been that way (since listobject.c rev 1.1); and the "if i >= 0" qualifier was added to libtypes.tex a bit over 6 years ago, with checkin comment correct description of list.insert() Hard call! I agree it should change, but if it breaks code the "but it was formally undefined" comeback doesn't really warm peoples' hearts. first-one-to-suggest-a-future-stmt-dies-ly y'rs - tim

Tim Peters <tim.one@home.com>:
I never noticed it, but agree it's strange. Did you open a feature request on SourceForge?
Feature request? Heck, if Guido green-lights this I'll fix it myself. I haven't looked at the code yet but I'll be deeply surprised if it takes me longer than half an hour to nail this bug.
Hard call! I agree it should change, but if it breaks code the "but it was formally undefined" comeback doesn't really warm peoples' hearts.
If we're going to "fix" division, we sure ought to fix this. I've grown so used to Python being a smooth, consistent tool that fits comfortably in my hand that I found this really quite shocking. -- <a href="http://www.tuxedo.org/~esr/">Eric S. Raymond</a> "Both oligarch and tyrant mistrust the people, and therefore deprive them of arms." --Aristotle

Eric S. Raymond wrote:
If this is fixed, i think we should do a complete job of it and make sure exceptions are raised when the index is out of range. Notice (in current Python): >>> a = [1, 2, 3, 4] >>> a.insert(999, 0) >>> a [1, 2, 3, 4, 0] >>> a.insert(-999, 0) >>> a [0, 1, 2, 3, 4, 0] So what's happening is that Python is silently clipping the index to [0..n]. To bring this in line with indexing behaviour, it should not only interpret values in the range [-n..n], but also raise IndexError when the value is outside of [-n..n]. (Compare to pop() -- the behaviour i'm suggesting is exactly what pop() does, except that the range for pop() is [-n..n-1].) This has the potential for breaking code, and so the transition should probably be done with a minor-version's worth of warning, but i think if we're going to change it we should make it right. When this is done, i believe we'll be down to exactly two ways of handling sequence indices -- (a) x and y are silently clipped to [-n..n-1] *only* in an [x:y]-style slice (b) in all other cases, an IndexError is raised if the index is out of range and these two cases are easy to separate and explain, and all will be consistent in its interpretation of negative numbers. Such simplicity would be nice to have. -- ?!ng "Computers are useless. They can only give you answers." -- Pablo Picasso

On 26 August 2001, Ka-Ping Yee said:
By "minor version" do you mean 2.2 -> 2.3, or 2.2 -> 2.2.1? I presume the former -- we're not allowed to make incompatible changes on point releases anymore! Of course, this implies a f***** statement. (I'm not going to say the word, Tim said the first one who does dies...) Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ If you and a friend are being chased by a lion, it is not necessary to outrun the lion. It is only necessary to outrun your friend.

[Eric S. Raymond]
I never noticed it, but agree it's strange. Did you open a feature request on SourceForge? Note that array objects (created by the array module) share this behavior.
The reference manual says "same as s[i:i] = [x] if i >= 0" which of course doesn't cover the i < 0 case.
Which formally means its behavior is undefined.
David Beasley's reference says "Inserts x at index i" which sounds like the behavior I was expecting but didn't get.
Ya, so file a bug report with David <wink>.
Only Guido *may* be able to say for sure. Plausible: the behavior for i<0 was deliberate at the start, and when Python *grew* negative indices (it didn't always accept them), fear of incompatibility prevented changing .insert behavior (in the other cases where negative indices "grew a meaning", the old behavior was to raise an exception; but .insert accepted them silently). Digging thru CVS, the current behavior for i<0 has always been that way (since listobject.c rev 1.1); and the "if i >= 0" qualifier was added to libtypes.tex a bit over 6 years ago, with checkin comment correct description of list.insert() Hard call! I agree it should change, but if it breaks code the "but it was formally undefined" comeback doesn't really warm peoples' hearts. first-one-to-suggest-a-future-stmt-dies-ly y'rs - tim

Tim Peters <tim.one@home.com>:
I never noticed it, but agree it's strange. Did you open a feature request on SourceForge?
Feature request? Heck, if Guido green-lights this I'll fix it myself. I haven't looked at the code yet but I'll be deeply surprised if it takes me longer than half an hour to nail this bug.
Hard call! I agree it should change, but if it breaks code the "but it was formally undefined" comeback doesn't really warm peoples' hearts.
If we're going to "fix" division, we sure ought to fix this. I've grown so used to Python being a smooth, consistent tool that fits comfortably in my hand that I found this really quite shocking. -- <a href="http://www.tuxedo.org/~esr/">Eric S. Raymond</a> "Both oligarch and tyrant mistrust the people, and therefore deprive them of arms." --Aristotle

Eric S. Raymond wrote:
If this is fixed, i think we should do a complete job of it and make sure exceptions are raised when the index is out of range. Notice (in current Python): >>> a = [1, 2, 3, 4] >>> a.insert(999, 0) >>> a [1, 2, 3, 4, 0] >>> a.insert(-999, 0) >>> a [0, 1, 2, 3, 4, 0] So what's happening is that Python is silently clipping the index to [0..n]. To bring this in line with indexing behaviour, it should not only interpret values in the range [-n..n], but also raise IndexError when the value is outside of [-n..n]. (Compare to pop() -- the behaviour i'm suggesting is exactly what pop() does, except that the range for pop() is [-n..n-1].) This has the potential for breaking code, and so the transition should probably be done with a minor-version's worth of warning, but i think if we're going to change it we should make it right. When this is done, i believe we'll be down to exactly two ways of handling sequence indices -- (a) x and y are silently clipped to [-n..n-1] *only* in an [x:y]-style slice (b) in all other cases, an IndexError is raised if the index is out of range and these two cases are easy to separate and explain, and all will be consistent in its interpretation of negative numbers. Such simplicity would be nice to have. -- ?!ng "Computers are useless. They can only give you answers." -- Pablo Picasso

On 26 August 2001, Ka-Ping Yee said:
By "minor version" do you mean 2.2 -> 2.3, or 2.2 -> 2.2.1? I presume the former -- we're not allowed to make incompatible changes on point releases anymore! Of course, this implies a f***** statement. (I'm not going to say the word, Tim said the first one who does dies...) Greg -- Greg Ward - just another /P(erl|ython)/ hacker gward@python.net http://starship.python.net/~gward/ If you and a friend are being chased by a lion, it is not necessary to outrun the lion. It is only necessary to outrun your friend.
participants (4)
-
Eric S. Raymond
-
Greg Ward
-
Ka-Ping Yee
-
Tim Peters