Python 变量赋值与切片语法(in-place 修改 vs 重新赋值)
这是一个非常经典的 Python 变量赋值与切片语法问题。虽然这两行代码看起来“效果相似”,但它们的底层语义是不同的
重点区别在于是否修改原列表 nums1
的内存对象(in-place 修改 vs 重新赋值)。
✅ 两句代码分别是什么意思?
① nums1[:] = sorted_list
这是“原地修改”(in-place modification)
nums1[:]
表示对原列表的所有元素进行切片操作(整个列表);nums1[:] = ...
会把原来的列表内容就地替换为sorted_list
中的内容;- ✅ 不会改变 nums1 本身的引用地址;
- ✅ 通常用于在函数中更新“传进来的列表”,让调用者能感知到修改。
nums1 = [1, 2, 3]
sorted_list = [4, 5, 6]
nums1[:] = sorted_list
print(nums1) # [4, 5, 6]
- 内存地址不变:
id_before = id(nums1)
nums1[:] = sorted_list
id_after = id(nums1)
print(id_before == id_after) # True ✅
② nums1 = sorted_list[:]
这是“重新赋值”(rebinding)
sorted_list[:]
是一个sorted_list
的浅拷贝;- 然后用
nums1 = ...
把nums1
指向了新列表; - ❌ 不会影响原来的
nums1
对象(原列表的内存地址变了); - 原本指向
nums1
的其他变量或引用会失效。
nums1 = [1, 2, 3]
sorted_list = [4, 5, 6]
nums1 = sorted_list[:]
print(nums1) # [4, 5, 6]
- 地址发生变化:
nums1 = [1, 2, 3]
id_before = id(nums1)
nums1 = [4, 5, 6][:]
id_after = id(nums1)
print(id_before == id_after) # False ❌
🧪 举个更明确的例子
def update_list(nums1, sorted_list):nums1[:] = sorted_lista = [1, 2, 3]
b = [9, 9, 9]
update_list(a, b)
print(a) # [9, 9, 9] ✅ 被修改了
vs
def update_list(nums1, sorted_list):nums1 = sorted_list[:]a = [1, 2, 3]
b = [9, 9, 9]
update_list(a, b)
print(a) # [1, 2, 3] ❌ 没有变化
🧠 总结对比
写法 | 是否修改原列表 | 是否保留引用地址 | 用途 |
| ✅ 是(就地修改) | ✅ 是 | 改变传入列表的内容 |
| ❌ 否(创建新列表) | ❌ 否 | 创建新的副本或重新赋值变量 |
✅ 什么时候用哪一个?
- 如果你想更新一个传入的列表变量,让外部变量感知到,用
nums1[:] = ...
- 如果你想让
nums1
拿到一份新的拷贝,和旧的nums1
无关,用nums1 = ...[:]