前几天学习群中有朋友问了一个奇怪的问题:
l = [1, 2, 3, 4, 5, 6]
for v in l:
del l[0]
print(l)
# [4, 5, 6]
l = [1, 2, 3, 4, 5, 6]
for v in l[:]:
del l[0]
print(l)
# []
刚看到也是觉得奇怪,平时很少会在for in 遍历时删除列表元素,第二中写法和第一种写法上只是l和l[:]不同,为什么结果会那么奇怪? 先把影响结果的因素放在这里:
- for in 遍历是触发可迭代对象的
__iter__(),获取迭代器对象执行__next__()方法向后迭代列表 - 列表是使用顺序表实现的,当删除前面的元素时,后面的元素会向前移动,补上前面的空值位置,而next的位置不变(后面通过画图解释)
- l[:]是获取l的副本,属于浅拷贝,l[:]和l是两个不同的对象,所以当使用for in遍历l[:],是遍历的l[:],删除l中的元素不会影响对l[:]的迭代
好了,下面一点一点看一下为什么会产生以上问题:
for in 实现的while实现:
l = [1, 2, 3, 4, 5, 6]
for i in l:
print(i)
# 等价写法:
i = 0
iter_l = iter(l)
while True:
try:
print(next(iter_l))
except StopIteration as e:
print('迭代结束')
break
迭代列表流程图

那如果在遍历列表时同时删除元素,会如下图
