为何列表x中保留偶数?Python遍历修改列表的迭代异常
遍历列表时移除元素为何会跳过偶数?
先看你给出的代码和现象:
x = [1,2,3,4,5,6,7,8,9,10] y = [] for i in x: x.remove(i) if i%2 == 0: continue elif len(x) == 5: break y.append(i) print(x) # output [2, 4, 6, 8, 10] print(y) # output [1, 3, 5, 7]
从打印的迭代过程能看到,循环直接跳过了2、4这些偶数,核心原因是Python的for循环基于迭代器工作,迭代器会按索引顺序逐个取元素,而你在循环中修改了原列表的结构,导致元素移位,跳过了本该遍历的元素。
具体过程拆解:
- 初始时,
x = [1,2,3,4,5,6,7,8,9,10],for循环创建的迭代器从索引0开始取元素,第一次拿到i=1。 - 调用
x.remove(1)后,列表变成[2,3,4,5,6,7,8,9,10],此时迭代器的下一个目标是索引1(已经处理过索引0),而索引1对应的元素是3,所以下一次循环的i=3,直接跳过了现在在索引0的2。 - 同理,移除3后列表变成
[2,4,5,6,7,8,9,10],迭代器下一个取索引2,对应元素5,又跳过了索引1的4。 - 这个过程一直持续,所有偶数都因为元素移位被迭代器跳过,最终留在了x里。
解决办法
要避免这种问题,核心是不要在遍历原列表的同时修改它的结构,可以用下面几种方式:
1. 遍历原列表的副本
这样原列表的修改不会影响迭代的序列:
x = [1,2,3,4,5,6,7,8,9,10] y = [] for i in x.copy(): # 遍历x的副本,而非原列表 x.remove(i) if i%2 == 0: continue elif len(x) == 5: break y.append(i) print(x) # [4,6,8,10,2](顺序可能变化,但都是偶数) print(y) # [1,3,5,7]
2. 反向遍历列表
反向遍历的时候,移除末尾的元素不会影响前面元素的索引,所以不会出现跳过的情况:
x = [1,2,3,4,5,6,7,8,9,10] y = [] for i in reversed(x): x.remove(i) if i%2 == 0: continue elif len(x) == 5: break y.append(i) y.reverse() # 因为反向遍历,需要反转y恢复顺序 print(x) # [2,4,6,8,10] print(y) # [1,3,5,7]
3. 用列表推导式分离元素(更简洁)
如果你的需求只是分离奇偶元素,完全不需要在循环里修改原列表,直接用列表推导式更高效:
x = [1,2,3,4,5,6,7,8,9,10] y = [num for num in x if num % 2 != 0][:4] # 取前4个奇数 x = [num for num in x if num % 2 == 0] print(x) # [2,4,6,8,10] print(y) # [1,3,5,7]
内容的提问来源于stack exchange,提问作者k1dr0ck
相关产品推荐
相关产品推荐

