Python中循环调用list.pop(i)为何未弹出预期索引元素?
问题原因
Python列表的pop(i)是原地修改列表的方法:当你弹出索引为i的元素后,列表中i位置之后的所有元素会整体向前移动一位,列表长度同步减1,后续操作都是基于修改后的新列表执行,而非最初定义的原始列表。
你写的循环中i从0递增到2,每次弹出的是「当前修改后的列表对应i位置的元素」,并非初始列表索引0、1、2的三个元素,逐轮拆解运行过程就能看到偏差:
- 初始状态:
ls = ['hi', 'bye', 'cya', 'hello', 'nope'],i=0 - 第一轮循环:pop(0)弹出元素'hi'存入结果,原列表自动补位为
['bye', 'cya', 'hello', 'nope'],i自增为1 - 第二轮循环:pop(1)操作的是新列表索引1的元素'cya',弹出后原列表变为
['bye', 'hello', 'nope'],i自增为2 - 第三轮循环:pop(2)操作的是新列表索引2的元素'nope',弹出后原列表变为
['bye', 'hello'],循环结束
注:你贴出的实际输出中ls_popped第二个元素为'bye'属于笔误,按代码逻辑运行得到的弹出列表应为
['hi', 'cya', 'nope'],和预期不符的核心逻辑是一致的。
修正方案
如果你的预期是弹出初始列表前3个元素('hi'、'bye'、'cya'),剩余后两个元素,可以用以下两种写法:
- 固定弹出列表头部
每次弹出索引0的元素即可,因为弹出头部后,下一个需要的元素会自动补到0索引位,不需要额外调整索引:
ls = ['hi', 'bye', 'cya', 'hello', 'nope'] ls_popped = [] i = 0 while i < 3: ls_popped.append(ls.pop(0)) i += 1 print(ls) # 输出: ['hello', 'nope'] print(ls_popped) # 输出: ['hi', 'bye', 'cya']
- 从后往前弹出元素
如果需要按索引弹出连续段元素,从最大的索引开始往前弹,就不会因为列表移位影响前面元素的索引,弹出后反转结果列表即可得到正序:
ls = ['hi', 'bye', 'cya', 'hello', 'nope'] ls_popped = [] for i in range(2, -1, -1): ls_popped.append(ls.pop(i)) ls_popped.reverse() print(ls) # 输出: ['hello', 'nope'] print(ls_popped) # 输出: ['hi', 'bye', 'cya']
内容的提问来源于stack exchange,提问作者Mr Habibbi
相关产品推荐
相关产品推荐

