对于具有枚举的循环,当在循环内删除元素时,不会抛出索引超出范围错误吗?
L = [1, 4, 8, 5]
try:
for i,item in enumerate(L):
print("Value of {} is {}".format(i, item))
del L[i]
except IndexError as e:
print("Index error: {err}.".format(err=e))
输出:
Value of 0 is 1
Value of 1 is 8
此代码导致错误
L = [1, 4, 8, 5]
try:
for i in range(len(L)):
print("Item:", L[i])
del(L[i])
except IndexError as e:
print("Error:", e)
输出:
Item: 1
Item: 8
Error: list index out of range
答案 0 :(得分:1)
这两个代码错误(请参阅How to remove items from a list while iterating?),但两种情况下的症状都不同。
在第一种情况下,您在L
上迭代。缩短L
会使迭代结束更快(注意一些项被跳过,因为缩短列表会混淆内部迭代器,这会引发StopIteration
,从而停止for
循环)
您可以使用while
循环创建第一个案例的等效代码:
L = [1, 4, 8, 5]
try:
i = 0
while i < len(L):
print("Item:", L[i])
del(L[i])
i += 1
except IndexError as e:
print("Error:", e)
或模仿for
循环捕获StopIteration
迭代器上next
引发的enumerate
异常这一事实:
e = enumerate(L)
while True:
try:
i,item = next(e)
print("Value of {} is {}".format(i, item))
del L[i]
except StopIteration:
break
你得到相同的结果,因为len(L)
在每次迭代时被计算,所以索引不能越界(但结果也不是很有用)
在第二种情况下,您使用初始列表大小计算了range(len(L))
。所以过了一会儿,索引超出了缩短列表的范围。
第一种情况不会崩溃,但结果很难理解,实现定义,不能依赖。不要这样做。
答案 1 :(得分:0)
在带范围的第二个代码中,解释器实际上扩展了你的范围循环,因此它会尝试打印(L [2])而你的列表只有两个值。