Python列表原地修改疑问:nums[:]与nums=赋值为何产生不同数组旋转结果?
为什么
nums = ...和nums[:] = ...在原地修改列表时结果不同? 这是个非常经典的Python列表引用问题,核心区别在于两种赋值方式操作的是完全不同的对象:一个是重新绑定变量指向,另一个是直接修改原列表的内容。
先拆解你的场景
你写的rotate函数要求原地修改传入的nums列表,不能返回新列表。我们分别看两种赋值的行为:
1. nums = nums[n-k:] + nums[:n-k]:只是换了变量的指向
函数里的nums本质上是一个局部变量——它一开始和你调用函数时传入的列表指向同一个内存对象,但当你执行nums = 新列表时:
- Python会先创建
nums[n-k:] + nums[:n-k]这个新的列表对象; - 然后把局部变量
nums的指向从原来的列表,改成这个新创建的列表; - 而你最初传入的那个原列表,自始至终都没有被修改过。
举个直观的例子:假设你在外部定义my_nums = [1,2,3,4,5,6,7],然后调用rotate(my_nums, 3)。函数里的nums一开始和my_nums指向同一个列表,但执行nums = ...后,nums指向了新的[5,6,7,1,2,3,4],而my_nums仍然指向原来的[1,2,3,4,5,6,7],所以外部看不到变化。
你可以在函数里加两行代码验证:
print(id(nums)) # 赋值前的id,和外部列表的id一致 nums = nums[n-k:] + nums[:n-k] print(id(nums)) # 赋值后的id,是一个全新的数值,说明是新对象
2. nums[:] = nums[n-k:] + nums[:n-k]:原地修改原列表
nums[:]是对整个列表的切片引用,它代表的是原列表所有元素占据的内存区域。当你给它赋值时:
- Python不会创建新的列表对象,而是把右边拼接出来的元素,逐个替换到原列表的对应位置中;
- 整个过程中,
nums变量的指向始终没有变(还是原来的那个列表对象),只是原列表的内容被修改了。
同样用id验证:
print(id(nums)) # 赋值前的id nums[:] = nums[n-k:] + nums[:n-k] print(id(nums)) # 赋值后的id和之前完全一样,说明还是原来的对象
总结一下
- 如果题目要求原地修改列表(比如这道题明确说明
modify nums in-place instead),必须使用nums[:] = ...这种直接修改原列表内容的方式,或者其他原地操作(比如三次反转法); nums = ...只是在函数内部创建了新列表,和外部传入的原列表没有任何关系,自然不会改变原数组。
内容的提问来源于stack exchange,提问作者QUEEN
相关产品推荐
相关产品推荐

