Python函数外部列表未更新:按赋值传递为何失效?
问题:LeetCode删除有序数组重复项时外部列表未更新的原因
我在解决LeetCode「删除有序数组中的重复项」问题时,大量测试用例无法通过。本地运行测试代码后发现:调用removeDuplicates()函数时,函数内部的nums被更新,但外部的nums完全没变化。我试过用nums = list(set(nums))替代清空列表再追加元素的操作,依然没用。为什么会这样?Python列表作为参数传递时不是按赋值传递吗?
测试代码
def removeDuplicates(nums): nums_ = set(nums) nums = [] for i in nums_: nums.append(i) print(nums) # not working even if I do nums = list(set(nums)) instead of all lines above return len(nums) nums = [1,1,2] expectedNums = [1,2] k = removeDuplicates(nums) if k != len(expectedNums): print(False) for i in range(k): if nums[i] != expectedNums[i]: print(False) print(nums, expectedNums) break
运行输出
Output:
False
[1, 1, 2]
[1, 2]
解答
核心原因:Python的参数传递是「按对象引用传递」
你误解了Python的参数传递机制——它不是简单的赋值传递,而是按对象引用传递:
- 当你把外部的
nums传入函数时,函数里的局部变量nums只是拿到了原列表对象的引用,和外部变量指向同一个内存地址。 - 但如果你在函数里执行
nums = []或者nums = list(set(nums)),这相当于给局部变量nums重新绑定了一个新的列表对象,此时它和外部的nums已经指向不同的内存地址了,外部的列表自然不会有任何变化。
另外还要注意:用set处理有序数组会直接打乱元素顺序,而LeetCode的题目要求是在原数组上原地修改,且保持元素的相对顺序,这也是你的解法不符合题目要求的关键问题。
正确的原地修改解法(双指针法)
因为数组是有序的,重复元素必然相邻,用双指针可以高效完成原地去重:
def removeDuplicates(nums): if not nums: return 0 # 慢指针i:指向已去重数组的最后一位 i = 0 # 快指针j:遍历整个数组寻找新元素 for j in range(1, len(nums)): if nums[j] != nums[i]: i += 1 nums[i] = nums[j] # 返回去重后的数组长度 return i + 1 nums = [1,1,2] expectedNums = [1,2] k = removeDuplicates(nums) if k != len(expectedNums): print(False) else: passed = True for i in range(k): if nums[i] != expectedNums[i]: passed = False print(f"第{i}位元素不符:{nums[i]} != {expectedNums[i]}") break print("测试通过" if passed else False)
运行结果
测试通过
内容的提问来源于stack exchange,提问作者TheReal_Skywalker
相关产品推荐
相关产品推荐

