python:迭代弹出元素时出现列表索引超出范围错误

45 投票
12 回答
831304 浏览
提问于 2025-04-15 16:23

我写了一个简单的Python程序

l=[1,2,3,0,0,1]
for i in range(0,len(l)):
       if l[i]==0:
           l.pop(i)

在这一行if l[i]==0:上,我遇到了“列表索引超出范围”的错误。

经过调试,我发现i的值在增加,而列表的长度在减少。
不过,我设置了循环的结束条件是i < len(l)。那为什么还会出现这个错误呢?

12 个回答

6

你在遍历列表的时候改变了它的大小,这可能不是你想要的,这也是你出错的原因。

补充:正如其他人所说和评论的那样,列表推导式通常是更好的选择,尤其是在回答这个问题时。我提供这个作为一个替代方案,虽然不是最好的答案,但它仍然能解决问题。

所以,顺便提一下,你也可以使用 filter,它允许你调用一个函数来筛选出你不想要的列表项。

举个例子:

>>> l = [1,2,3,0,0,1]
>>> filter(lambda x: x > 0, l)
[1, 2, 3]

活到老,学到老。简单的东西更好,除非你需要复杂的东西。

19

表达式 len(l) 只会在 range() 函数被计算的时候执行一次。那时候创建的范围对象是固定的,它不会改变;它根本不知道 l 这个对象的任何信息。

顺便说一下,l 这个名字不太好!它看起来像数字1,或者大写字母I。

67

你在遍历列表 l 的时候,正在减少它的长度,所以当你接近范围语句中的索引末尾时,有些索引就不再有效了。

看起来你想做的是:

l = [x for x in l if x != 0]

这个操作会返回一个新的列表,里面没有任何值为零的元素(这个操作叫做 列表推导,顺便提一下)。你甚至可以把最后那部分简化成 if x,因为非零数字会被认为是 True

在你写的代码中,并没有 i < len(l) 这样的循环结束条件,因为 len(l) 是在循环开始前就计算好的,而不是在每次循环时重新计算。不过,你可以这样写:

i = 0
while i < len(l):
   if l[i] == 0:
       l.pop(i)
   else:
       i += 1

撰写回答