Har*_*nam 21 python python-2.7
我有一份清单
a = [1, 2, 3]
Run Code Online (Sandbox Code Playgroud)
我什么时候做的
a.insert(100, 100)
[1, 2, 3, 100]
Run Code Online (Sandbox Code Playgroud)
因为列表最初的大小为4,我试图在索引100处插入值,它表现得像追加而不是抛出任何错误,因为我试图插入一个甚至不存在的索引.
它应该不扔
IndexError:列表赋值索引超出范围
当我尝试做的时候会抛出异常
a[100] = 100
Run Code Online (Sandbox Code Playgroud)
问题: 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]
Run Code Online (Sandbox Code Playgroud)
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邮件列表线程中看到.如果您发现线程链接已更改,您可以通过谷歌搜索在python dev开头附加的问题标题找到答案.
alf*_*sin 15
来自文档:
list.insert(i,x)
在给定位置插入一个项目.第一个参数是要插入的元素的索引,因此a.insert(0,x)插入列表的前面,而a.insert(len(a),x)等同于a.append( X).
所以从技术上讲,当你这样做时a.insert(100, 100),确保100将在 100 之前的索引中插入,在这种情况下,索引3.
此外,我们可以看一下实现:
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
Py_ssize_t i, n = Py_SIZE(self);
PyObject **items;
if (v == NULL) {
PyErr_BadInternalCall();
return -1;
}
if (n == PY_SSIZE_T_MAX) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more objects to list");
return -1;
}
if (list_resize(self, n+1) == -1)
return -1;
if (where < 0) {
where += n;
if (where < 0)
where = 0;
}
if (where > n) // <-- Here the implementation handles indexes > list-len
where = n;
items = self->ob_item;
for (i = n; --i >= where; )
items[i+1] = items[i];
Py_INCREF(v);
items[where] = v;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
小智 9
文件说:
L.insert(index, object) # insert object before index
Run Code Online (Sandbox Code Playgroud)
因此,当您尝试在索引100处插入时,它将真正获得100之前的列表上的现有索引.
static int
ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
{
...
if (where > n)
where = n;
...
}
Run Code Online (Sandbox Code Playgroud)
所以这回答了如何做的问题.
从哲学上讲,列表不是数组,并且有许多列表操作可以容忍奇怪的索引.例如,l [1:1000]将返回[2,3].这对程序员来说都是一种方便.
Python 的创建者 Guido van Rossum 在python-dev邮件列表上的评论(查看2014 年 9 月的档案;根据我的经验,特定消息的确切 URL 会不时发生变化),以回应 OP 交叉发布此问题在该名单上:
2014 年 9 月 15 日星期一下午 3:46,马克·劳伦斯 (Mark Lawrence) 写道:
我认为它是基于切片的概念。从文档“s.insert(i, x) - 将 x 插入 s 中由 i 给出的索引处(与 s[i:i] = [x] 相同)”。
啊,对了。它匹配像 s[100:] 这样的东西,如果 s 小于 100,则它是空字符串。
在另一个回应中:
这个功能从 Python 诞生之初就已经存在,即使我们都同意它是错误的,我们也无法更改它——它只会破坏太多现有代码。我不太记得为什么要这样做,但这绝对是一个有意识的选择;可能存在某种对称性或边缘情况。(请注意,它在另一端也以这种方式工作 - 如果 a 的元素少于 100 个,a.insert(-100, x) 将在 a 的开头插入 x。)
归根结底,这种事情是一个设计决定。几乎总是存在相互竞争的问题,而且你永远找不到每个人都直观的东西。只要看看不同的语言有多少种方式处理像 True 和 False 这样的基本概念(在某些语言中,它们与数字 1 和 0 相同;在某些语言中,任何非零都是 True;在某些语言中 True 和 False 与数字 1 和 0 相同)。字符“1”和“0”(是的,真的!);在某些语言中,它们与数字或任何其他非严格布尔类型完全不兼容;在某些语言中,空容器是 False,在其他语言中,它们是 True;选择无穷无尽)。或者看看 nil/null/None,它们也与布尔值和其他计算有有趣的交互。有些语言甚至有 Maybe。
Python 处理列表插入的方式在某些情况下很方便,并且有足够多的人发现它很有用,他们编写的代码利用并依赖于这种方式的插入行为。也许文档可以更清晰一些,但实际上并没有那么不清楚;无论如何,一旦你尝试了它,你就会看到它的作用,并相应地编写你的 Python 代码。
| 归档时间: |
|
| 查看次数: |
4958 次 |
| 最近记录: |