Python风格列表元素交换触发索引越界错误的原因解析
为什么Python并行赋值交换会触发索引越界,而分步交换却正常?
嘿,这个问题其实是Python并行赋值的求值顺序坑,我之前也踩过!咱们拿你的例子一步步拆解,就能明白原因了。
先回顾你的场景:
nums = [-10,-3,-100,-1000,-239,1] # 待交换列表 i = 5 # 目标索引
你想交换nums[i]和nums[nums[i]-1],期望得到[1, -3, -100, -1000, -239, -10],但用并行赋值时直接触发了索引越界,分步写却没问题。
并行赋值的问题根源
先看报错的代码:
nums[i], nums[nums[i]-1] = nums[nums[i]-1], nums[i] # 触发IndexError
很多人以为Python并行赋值是先把右边所有值都算好,再一次性赋值给左边,但其实左边的赋值是按顺序执行的,而且后面的索引计算会用到前面修改后的列表值!
咱们走一遍你的例子的执行流程:
- 先计算右边的两个值(从左到右):
- 第一个值:
nums[nums[i]-1]→nums[1-1] = nums[0] = -10 - 第二个值:
nums[i] = nums[5] = 1
此时右边的结果是(-10, 1),这一步没问题。
- 第一个值:
- 开始给左边赋值(同样从左到右):
- 第一步:
nums[i] = -10→ 列表变成[-10,-3,-100,-1000,-239,-10](nums[5]被改成了-10) - 第二步:
nums[nums[i]-1]→ 这里的nums[i]已经是修改后的-10了,计算索引就是-10 -1 = -11,这明显超出了列表的合法索引范围(列表长度6,索引只能是0-5),直接触发索引越界错误!
- 第一步:
分步交换为什么没问题?
再看你的分步代码:
t = nums[i] nums[i] = nums[t-1] nums[t-1] = t
核心原因是你提前把nums[i]的初始值存在了临时变量t里,后续所有索引计算用的都是t这个固定值,不会被列表的修改影响:
t = nums[i]→t = 1,这个值不会变了nums[i] = nums[t-1]→nums[5] = nums[0] = -10,列表变成[-10,-3,-100,-1000,-239,-10]nums[t-1] = t→nums[0] = 1,最终得到你想要的结果
一句话总结
Python并行赋值的左边表达式是按顺序求值的,后面的索引会受前面赋值操作的影响;而分步交换用临时变量锁死了初始索引值,避免了这个问题。
内容的提问来源于stack exchange,提问作者Psyduck
相关产品推荐
相关产品推荐

