我写了一些代码,其中forloop索引在一个范围内变化,具体取决于列表的长度,并且列表的长度在循环内是可变的。这是一个简化的代码:
>>> ml = [1,2,3]
>>> for i in range(0, len(ml)):
... if ml[i] == 2:
... ml.pop(i)
... i
...
0
2
1
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
IndexError: list index out of range
我猜{for len(ml)
在forloop的第一次迭代中被评估一次,而不是在后面的迭代中,因此索引超出范围。
但是可以在迭代中更新索引范围吗?感谢。
答案 0 :(得分:4)
new_list = [x for x in my_list if x != 2]
好多了或
new_list = filter(lambda x:x!=2,my_list)
你不应该在迭代列表时真正删除元素,除非你有一个非常非常好的(我从来没有听说过这么好)原因
如果您希望元素替换当前列表
my_list[:] = [x for x in my_list if x != 2]
或者你可以简单地覆盖它,让pythons非常好的垃圾收集器删除旧的
my_list = [x for x in my_list if x != 2]
答案 1 :(得分:3)
range(0, len(ml))
评估一次,并生成i
的值列表。
您可以通过while循环简单地替换for循环:
i = 0
while i < len(ml):
if ml[i] == 2:
ml.pop(i)
continue
i+=1
答案 2 :(得分:1)
这种行为是有道理的,因为你实际上没有遍历列表,而是在范围内:
ml = [1, 2, 3]
for i in range(0, len(ml)):
print(i)
提供以下输出:
0
1
2
使用for item in ml:
实际上遍历列表:
ml = [1, 2, 3]
for i in ml:
if i == 2:
ml.pop(i)
print(i)
结果:
1
2
回应此处的评论,可以更好地了解发生了什么:
ml = [1, 2, 3, 4, 5, 6, 7]
for i in ml:
if i == 2:
ml.pop(1) # pop second element in list
print(i)
给出以下输出:
1
2
4
5
6
7
使用while循环可以得到相同的结果:
ml = [1, 2, 3, 4, 5, 6, 7]
i = 0
while i < len(ml):
print(ml[i])
if ml[i] == 2:
ml.pop(i)
i+=1
1
2
4
5
6
7
这意味着您可以弹出元素,但是您无法确保所有元素都已正确处理。