Python 3.6遍历列表时删除元素,首次删除后循环异常原因咨询
遍历列表时删除元素导致循环异常的原因及解析
咱们先拆解你遇到的问题:你的代码执行后得到[0, 1, 3, 4],核心原因是Python的for循环遍历列表时,是基于列表的迭代器来逐个取元素,而当你修改原列表的长度(删除元素)时,迭代器的遍历位置会和列表实际元素的位置错位。
具体来走一遍你的代码执行流程:
- 初始列表
x = [0, 1, 2, 3, 4],for循环启动时,会创建一个指向这个列表的迭代器,迭代顺序是按索引0→1→2→3→4依次取元素。 - 前两次循环:
i=0和i=1都不满足删除条件,正常跳过。 - 第三次循环:
i=2满足条件,执行x.remove(2),此时列表变成[0, 1, 3, 4]——注意,原来在索引3的元素3现在移到了索引2的位置。 - 第四次循环:迭代器会继续取下一个位置的元素,也就是原来的索引3(因为迭代器已经走过了索引0、1、2),但现在列表的索引3对应的元素是
4,所以i=4不满足删除条件,循环直接结束。 - 结果就是
3被“漏掉”了,没有被删除。
那是不是修改所有正在遍历的可迭代对象都会出问题?其实分情况:
- 可变序列(比如列表、集合):如果遍历过程中修改了它们的长度(增删元素),大概率会出现遍历错位、元素跳过甚至报错的情况。比如遍历集合时删除元素,直接会抛出
RuntimeError: Set changed size during iteration。 - 不可变序列(比如字符串、元组):这类对象本身无法修改,所以不存在遍历中修改的问题。
- 其他可迭代对象:比如字典,Python 3中遍历
dict.items()时,如果修改字典的键(增删键),会直接报错;但如果只是修改对应的值,不会影响遍历。
解决办法
最稳妥的方式是遍历原列表的副本,或者用列表推导式生成新列表:
- 遍历副本:
x = list(np.arange(5)) for i in x.copy(): # 或者 list(x) if i == 2 or i == 3: x.remove(i)
这样遍历的是初始列表的副本,删除原列表的元素不会影响遍历流程,最终会得到[0,1,4]。
- 列表推导式(更推荐,代码更简洁高效):
x = list(np.arange(5)) x = [i for i in x if i not in {2, 3}]
直接生成不包含目标元素的新列表,避免了遍历中修改原列表的风险。
内容的提问来源于stack exchange,提问作者Jed
相关产品推荐
相关产品推荐

