Python3中直接执行nums[i], nums[nums[i]-1]交换赋值的运行原理是什么?
Python3 中
nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]的执行逻辑解析 首先明确Python多重赋值的固定执行规则:
Python 中所有多重赋值操作都严格遵循两步流程:
- 从左到右计算等号右侧所有表达式的结果,按顺序存入临时元组缓存
- 从左到右将临时元组中的值,依次赋值给等号左侧的每个左值,每个左值的位置(比如索引)会在赋值前实时计算
我们用具体测试用例nums = [2, 1]、i = 0(预期交换后得到[1,2])来拆解两种写法的执行差异:
第一种写法的执行流程
对应代码:nums[i], nums[nums[i] - 1] = nums[nums[i] - 1], nums[i]
- 第一步:计算等号右侧所有表达式,生成临时元组
先算第一个右值nums[nums[i] - 1]:代入i=0得nums[0]=2,进一步计算得nums[2-1] = nums[1] = 1
再算第二个右值nums[i]:直接得nums[0] = 2
最终缓存的临时元组为(1, 2) - 第二步:按顺序给左侧左值赋值
第一个左值是nums[i]即nums[0],赋值为临时元组第一个值1 → 此时nums变为[1, 1]
第二个左值是nums[nums[i] - 1]:此时nums[i]已经被更新为1,所以计算索引得1-1=0,左值实际是nums[0],赋值为临时元组第二个值2 → 最终nums变为[2, 1],交换失败
第二种写法的执行流程
对应代码:x = nums[i] - 1; nums[i], nums[x] = nums[x], nums[i]
- 第一步:赋值操作开始前提前计算索引
x,此时nums[i]还未被修改,代入i=0得x = 2-1 = 1,x值固定不会再变 - 第二步:计算等号右侧所有表达式,生成临时元组
先算第一个右值nums[x]即nums[1] = 1,再算第二个右值nums[i] = 2,缓存的临时元组为(1, 2) - 第三步:按顺序给左侧左值赋值
第一个左值nums[i]即nums[0]赋值为1 → 此时nums变为[1, 1]
第二个左值是nums[x],x提前固定为1,所以是nums[1],赋值为2 → 最终nums变为[1, 2],交换成功
二者核心差异
差异完全来自等号左侧第二个索引的计算时机:
- 第一种写法中,左侧第二个索引
nums[i] - 1是在第一个左值赋值完成后才计算的,此时nums[i]已经被修改,索引会偏离预期 - 第二种写法中,索引x在所有赋值操作开始前就已经计算完成,后续赋值过程中x不会变化,能准确命中目标位置
内容的提问来源于stack exchange,提问作者Charlie
相关产品推荐
相关产品推荐

