正向遍历时删除元素会跳过下一个元素,因为删除后后续元素前移而循环索引已递增;推荐反向遍历+del或列表推导式。

不能边遍历边用 list.remove() 或 del 删除元素,否则会跳过下一个元素。
为什么正向遍历时删除会漏删?
因为列表索引实时变化:删掉索引 i 的元素后,原 i+1 位置的元素会前移到 i,但循环已执行完 i,直接跳到 i+1,导致新移过来的元素被跳过。
常见错误现象:[1,2,2,3,2] 中删所有 2,结果只剩一个 2。
示例(危险):
立即学习“Python免费学习笔记(深入)”;
nums = [1,2,2,3,2]
for x in nums:
if x == 2:
nums.remove(x) # ❌ 跳过相邻重复项推荐方案:反向遍历 + del
从后往前遍历,删除操作不影响尚未访问的索引,逻辑最直白、兼容性最好(Python 2/3 都适用)。
- 用
range(len(nums)-1, -1, -1)构造倒序索引 - 必须用
del nums[i]或nums.pop(i),不能用nums.remove(x)(后者仍需查找,且语义不清) - 注意:
pop()返回被删元素,del不返回,按需选择
示例:
nums = [1,2,2,3,2]
for i in range(len(nums)-1, -1, -1):
if nums[i] == 2:
del nums[i]更 Pythonic 的做法:列表推导式或 filter()
如果目标是“保留满足条件的元素”,优先用生成新列表的方式——语义清晰、无副作用、不易出错。
- 列表推导式最常用:
[x for x in nums if x != 2] - 需要复用判断逻辑时,用
filter(lambda x: x != 2, nums),但注意 Python 3 返回迭代器,需转list() - 性能上,推导式通常略快;内存上,两者都新建列表,原列表不变
注意:这不适用于“原地修改”有强约束的场景(如函数接收列表并要求就地清理)。
用 while + index() 要小心
有人写 while 2 in nums: nums.remove(2),看似简洁,但 in 和 remove() 每次都从头扫描,时间复杂度 O(n²),大数据量时明显变慢。
若坚持用 while,可配合 index() 避免重复扫描:
nums = [1,2,2,3,2]
while True:
try:
i = nums.index(2)
del nums[i]
except ValueError:
break但代码冗长,不如反向遍历或推导式直观。
真正容易被忽略的是:是否必须原地修改。多数时候,新建列表更安全;只有当明确要求复用原对象 ID(比如被其他变量引用、或用于 is 判断)时,才值得选反向遍历。


















