我有一个清单
a = [1, 2, 3]
当我做的时候
a.insert(100, 100)
[1, 2, 3, 100]
因为列表最初的大小为4,我试图在索引100处插入值,它表现得像追加而不是抛出任何错误,因为我试图插入一个甚至不存在的索引。
不应该抛出
IndexError:列表分配索引超出范围
异常,因为它抛出时 我试图做
a[100] = 100
问题: 1.任何想法为什么它被设计为静默处理它而不是通知用户异常?
个人意见:
让我们看看其他语言在这种情况下的表现如何:
Ruby:
> a = [1, 2]
> a[100] = 100
> a
=> [1, 2, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, 100]
ruby处理这个问题的方式非常清楚,至少对我来说听起来很有意义。
Java:
在java中,方法.add(index,value)如果应用索引超出范围(例如arraylist,linkedlist)将抛出 java.lang.IndexOutOfBoundsException。
所以我觉得要么它应该抛出异常(如java所做),要么在它们之间的范围内插入null(因为ruby处理它)。 但是在python中处理的无声方式只是令人沮丧。
更新(2014年9月16日IST上午8:30):
正如其中一位回答者所说,我在python-dev中发布了这个问题,我收到了回复。可以在此python dev mailing list thread中看到。如果你发现线程链接已经改变,你可以通过google search找到答案,在python dev的开头附加一个问题标题。
答案 0 :(得分:15)
来自 docs :
list.insert(i,x)
在给定位置插入项目。第一个参数是要插入的元素的索引,所以 a.insert(0,x)插入列表的前面,a.insert(len(a), x)相当于a.append(x)。
从技术上讲,当您执行a.insert(100, 100)
时,它确保{/ 1}}将在 100之前的索引中插入,在这种情况下,恰好是索引3。
此外,我们可以查看the implementation:
100
答案 1 :(得分:9)
文档说:
L.insert(index, object) # insert object before index
所以当你尝试在索引100处插入它时,它真的会在100之前获得列表中的现有索引。
答案 2 :(得分:5)
Perhaps the actual implementation will shed some light.
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
...
if (where > n)
where = n;
...
}
这样就回答了如何解决问题。
哲学上,列表不是数组,并且有许多列表操作可以容忍奇怪的索引。例如,l [1:1000]将返回[2,3]。这对程序员来说都是一种方便。
答案 3 :(得分:3)
a.insert(len(a), x)
supposed的行为与a.append(x)
的行为相同。在查看方法的source code之后:
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
Py_ssize_t i, n = Py_SIZE(self);
...
if (where > n)
where = n;
...
}
通过将len(a)
上方的任何int设置为n
,您将看到它以相同的方式处理n
上方的任何int。
因此:如果作为int >= len(a)
的第一个参数传递,任何list.append(x)
都会像list.insert(i, x)
一样。
官方python文档可能只推荐len(a)
作为一种方便的方法来确保您始终输入的数字大于列表的长度。
答案 4 :(得分:2)
Python的创建者Guido van Rossum在python-dev
邮件列表上的评论(查看September 2014 archives;根据我的经验,特定邮件的确切网址可能会不时发生变化),以回应OP在该清单上交叉提出这个问题:
2014年9月15日星期一下午3:46,马克劳伦斯 写道:
我认为它基于切片的概念。从文档" s.insert(i,x) - 在由i给出的索引处将x插入s(与s [i:i] = [x]相同)"。
啊,对。它匹配像s [100:]的thigs,如果s是空字符串 短于100。
在另一个回复中:
这个功能自Python早期就已经存在,即使我们都认为它是错误的,我们也无法改变它 - 它只会破坏过多的现有代码。我不记得为什么我这样做了,但这绝对是一个有意识的选择;可能是一些对称或边缘情况。 (注意它在另一端也是这样工作的 - 如果一个元素少于100个,a.insert(-100,x)将在a的开头插入x。)
最终,这种事情是一个设计决定。几乎总是存在竞争问题,你永远找不到对每个人都很直观的东西。只需看看不同语言处理概念的方式有多少,如True和False(在某些语言中,它们与数字1和0相同;在某些语言中,任何非零都是True;在某些语言中,True和False与字符' 1'和' 0'(是的,真的!);在某些语言中,它们与数字或任何其他非严格布尔类型完全不兼容;在某些语言中,空容器是假的,在其他语言中它们是真的;选择一直在继续)。或者看看nil / null / None,它们也与布尔和其他计算有趣的交互。有些语言甚至有可能。
Python处理列表插入的方式在某些情况下很方便,而且有足够的人发现它们编写的代码可以使用并依赖于插入行为。也许文档可能是 little 更清晰,但它真的不是那么不清楚;无论如何,一旦你尝试它,你会看到它的作用,并相应地编写你的Python代码。
答案 5 :(得分:1)
当您将单个元素插入列表时,列表的长度将只增加一个 - 不多于,而不是更少。
答案 6 :(得分:0)
不是将插入与项目分配进行对比,而是更类似于切片分配,因为两者都会改变列表的大小。
>>> a = [1, 2, 3]
>>> a[100:100] = [100]
>>> a
[1, 2, 3, 100]
切片也不会引发IndexError,因此与:
一致a.insert(100, 100)