拷贝、引用与可变对象
这类问题在 Python 初学阶段出现频率非常高:为什么我改了 new_list,original_list 也跟着变了?
原因通常不是“列表很奇怪”,而是你拿到的是同一个对象的引用。
赋值不是拷贝
original = [1, 2, 3]
new_list = original
new_list.append(4)
print(original) # [1, 2, 3, 4]
print(new_list) # [1, 2, 3, 4]
new_list = original 做的事不是复制列表,而是让两个变量指向同一个列表对象。
浅拷贝
下面这些方式都会创建新的外层列表:
items = [1, 2, 3]
a = items[:]
b = list(items)
c = items.copy()
但它们只复制一层
items = [[1, 2], [3, 4]]
copied = items.copy()
copied[0].append(99)
print(items) # [[1, 2, 99], [3, 4]]
print(copied) # [[1, 2, 99], [3, 4]]
因为外层列表虽然是新的,里面嵌套的子列表仍然指向同一批对象。
深拷贝
如果对象内部还有嵌套结构,就要考虑 copy.deepcopy():
import copy
items = [[1, 2], [3, 4]]
copied = copy.deepcopy(items)
copied[0].append(99)
print(items) # [[1, 2], [3, 4]]
print(copied) # [[1, 2, 99], [3, 4]]
为什么这件事重要
因为 Python 里很多对象都是可变的:
listdictset
如果你没有分清“我是在改原对象”还是“我是在改副本”,后面调试会非常痛苦。
我自己的判断方式
- 只写了
a = b:基本不是拷贝 - 只复制了最外层:浅拷贝
- 里面还有嵌套,且想完全独 立:深拷贝