從字面意思了解,拷貝即複制目前的對象。但是 隻有在容器對象(清單,元組,字典)才有拷貝這一概念,原子對象(數字,字元串)沒有拷貝這一說。
引入
普通的複制都是淺拷貝。
淺拷貝可以了解為A容器拷貝産生的B容器雖然是新的,但B容器裡的内容仍是舊的,其隻是簡簡單單的複制了A容器裡内容的引用,并沒在B容器裡建立真正的對象。而當我們修改B容器裡的内容時,會産生兩種結果:不可變對象會建構新的對象,其的id發生改變;而可變對象會根據引用去修改,結果其的改變會影響A容器裡對應部分也發生改變。
為了使容器中可變對象的修改互不影響,得到真正意義上的拷貝,遂引出深拷貝這一概念,深拷貝也稱為完全拷貝。
注:
id可以簡單認為是位址(其實不是),“id(obj)”函數可以列印出obj對象的id。
可變對象是指其的内容可以發生改變,具體為清單,字典;不可變對象則反之,具體為數字,字元串和元組。
結合代碼:
#!/usr/bin/env python
# coding=utf-8
from copy import copy, deepcopy
def id_print(old, new):
print 'old對象:', old
print 'new對象:', new
print 'old對象與new對象的id:%d, %d' % (id(old), id(new))
print 'old[0]與new[0]的id:%d, %d' % (id(old[0]), id(new[0]))
print 'old[1]與new[1]的id:%d, %d' % (id(old[1]), id(new[1]))
old = ['old', ['old', 1]]
# new = old[:] # 切片,産生淺拷貝
# new = list(old) # 清單的工廠函數,産生淺拷貝
# new = copy(old) # copy子產品的copy函數,産生淺拷貝
# new = deepcopy(old) # copy子產品的deepcopy函數,産生深拷貝
print '*' * 20 + '修改前' + '*' * 20
id_print(old, new)
new[0] = 'new' # 修改不可變對象
new[1][0] = 'new' # 修改可變對象的内容
print '*' * 20 + '修改後' + '*' * 20
id_print(old, new)
淺拷貝與深拷貝的運作結果将在下面分别呈現。
淺拷貝
解除對應注釋後,運作結果:
1)通過切片操作,工廠函數(list(),tuple(),dict())或copy子產品的copy函數産生的都是淺拷貝。
2)淺拷貝得到的兩個對象的id不同,但内容的id是相同的。若内容發生改變,不可變對象的id會變不同,彼此不影響;可變對象的id仍相同,彼此影響。
深拷貝
解除對應注釋後,運作結果:
1)使用copy子產品的deepcopy函數産生的是深拷貝。
2)深拷貝得到的兩個對象的id不同,内容中可變對象id不同,内容中不可變對象id相同。如果内容發生改變,不可變對象id變不同,彼此不影響;可變對象id仍然不同,彼此不影響。
參考自Python核心程式設計第二版6.20節;文中如有不恰當的地方,還望包容和指出,感謝