Python for循环工作原理是什么?为何遍历删元素会迭代异常
Python for 循环运行机制
Python 中遍历列表的for循环,底层依赖列表迭代器实现:
- 循环启动时,会先对列表调用
iter()拿到迭代器,迭代器内部维护一个从0开始的位置计数器 - 每轮循环自动调用迭代器的
next()方法,按计数器的值取列表对应位置的元素,之后计数器自增1 - 当计数器的值大于等于列表当前长度时,触发
StopIteration异常,循环直接终止
重点:迭代器不会在每轮循环时重置计数器,也不会感知列表长度变化带来的元素位置偏移
内层循环迭代次数异常的根因
问题出在遍历原列表的同时直接删除列表元素,触发了索引错位,以第四次while循环的执行为例:
- 进入第四次迭代时,
array初始值为[[1,1,0], [2,2,0], [3,3,0]],长度为3,迭代器计数器初始为0 - 第一轮for循环:取索引0的元素
[1,1,0],判断第三个值为0,执行del array[0],此时列表元素自动向前移位,变为[[2,2,0], [3,3,0]],执行continue,手动维护的index变量保持0不变 - 第二轮for循环:迭代器计数器自增到1,取当前列表索引1的元素
[3,3,0],判断第三个值为0,执行del array[0](此时index值仍为0),列表变为[[3,3,0]],再次执行continue,index保持0 - 第三轮for循环未触发:迭代器计数器自增到2,但此时列表长度仅为1,计数器值已大于等于列表长度,直接触发循环终止条件,因此仅能观察到2次迭代打印。
修复方案
禁止在遍历原列表时直接删除元素,任选以下一种方案即可:
- 方案1:遍历列表的浅拷贝,删除操作作用于原列表,不会干扰遍历流程
import time array = [[1, 1, 3], [2, 2, 3], [3, 3, 3]] while True: time.sleep(1) print(array) # 遍历列表副本,原列表修改不影响遍历进度 for proxy in array.copy(): print("iteration") if proxy[2] == 0: array.remove(proxy) continue proxy[2] -= 1 print("\n")
- 方案2:倒序遍历列表,删除元素时不会影响未遍历元素的索引位置
import time array = [[1, 1, 3], [2, 2, 3], [3, 3, 3]] while True: time.sleep(1) print(array) # 从最后一个元素向前遍历 for i in range(len(array)-1, -1, -1): print("iteration") proxy = array[i] if proxy[2] == 0: del array[i] continue proxy[2] -= 1 print("\n")
- 方案3:用列表推导式直接生成过滤后的新列表,逻辑更简洁不易出错
import time array = [[1, 1, 3], [2, 2, 3], [3, 3, 3]] while True: time.sleep(1) print(array) # 先统一扣减计数,再过滤掉计数为0的元素 for proxy in array: print("iteration") proxy[2] -= 1 array = [p for p in array if p[2] > 0] print("\n")
内容的提问来源于stack exchange,提问作者Timur
相关产品推荐
相关产品推荐

