核心概念
- 淺拷貝:創建新對象,但內部元素仍引用原對象的元素(指針拷貝)。
- 深拷貝:遞歸拷貝所有層級元素,完全獨立於原對象。
互動演示
>>> person = ['name', ['savings', 100]]
>>> hubby = person[:] # 切片淺拷貝
>>> wifey = list(person) # list() 淺拷貝
>>> [id(x) for x in (person, hubby, wifey)]
[3074051788, 3074061740, 3074061996] # 外層列表不同對象
>>> [id(y) for x in (person, hubby, wifey) for y in x]
[3074319552, 3073979916, 3074319552, 3073979916, 3074319552, 3073979916] # 內層列表同一對象
修改測試
>&>> hubby[0] = 'joe' # 修改不可變元素(字符串),創建新對象
>> wifey[0] = 'jane'
(person, hubby, wifey)
(['name', ['savings', 100]], ['joe', ['savings', 100]], ['jane', ['savings', 100]])
>> hubby[1][1] = 70 # 修改可變元素(內層列表),影響所有引用
>> (hubby, wifey, person)
(['joe', ['savings', 70]], ['jane', ['savings', 70]], ['name', ['savings', 70]])
原理解析
- 不可變對象(int、str、tuple)修改時實際是創建新對象,故淺拷貝看似獨立;
- 可變對象(list、dict、set)修改時在原內存地址上變更,淺拷貝共享引用會相互影響;
- 深拷貝(
copy.deepcopy())遞歸複製所有層級,徹底隔離。
代碼對比
import copy
original = [1, [2, 3], 4]
shallow = copy.copy(original)
deep = copy.deepcopy(original)
shallow[1].append(99)
print("original:", original) # [1, [2, 3, 99], 4] 受影響
print("deep:", deep) # [1, [2, 3], 4] 不受影響
最佳實踐建議
- 只包含不可變元素時,淺拷貝足夠;
- 嵌套可變結構且需完全隔離,必須用
copy.deepcopy();
- 自定義類可實現
__copy__ 和 __deepcopy__ 控制拷貝行為;
- 性能敏感場景考慮手動構建新對象而非通用深拷貝。