概念
官方解釋:Python中的賦值語句不復制對象,它們在目標和對象之間建立索引。對於可變項目或可變項目的集合,有時需要一個副本,以便可以更改一個副本而不更改其他副本。該模塊提供通用的淺層和深層copy操作。
淺copy
為什么有賦值還要copy呢?當有一個需求是要把一個數據放到我的程序里進行修改操作,但是還要保持原始數據不變。這個時候就需要我們的copy登場了
先提一個需求,我的程序需要對一個數據進行修改,但是我又要保持這個數據和修改之前保持一致。那我們怎么操作呢?
舉個例子:
import copy a = ['111', '222'] # 我們不對變量a進行修改,因為要保持數據和修改之前一致
b = a b[0] = '333' print(a, b) # ['333', '222'] ['333', '222'] 結果並沒有達到我們的要求
# 手動copy
a = ['111', '222']
b = list()
for i in a:
b.append(i)
b[0] = '333'
# ['111', '222'] ['333', '222'] 實現了要求
# copy就是起到了這個作用 a = ['111', '222'] b = copy.copy(a) c[0] = '333' print(a, c)
從上面的例子可以看出引用和copy的區別,但是這還不夠,看下面的例子:
深copy
a = ['111', '222', ['333', '444']] b = copy.copy(a) b[2][0] = '555' print(a, b) # ['111', '222', ['555', '444']] ['111', '222', ['555', '444']] # 我們的目的又達不到了,如何是好 # 手動deep copy a = ['111', '222', ['333', '444']]
# 遞歸copy def deep_copy(copy_list): b = list() for i in copy_list: if isinstance(i, list): i = deep_copy(i) b.append(i) return b b = deep_copy(a) b[2][0][0] = '555' print(a, b)
a = ['111', '222', ['333', '444']]
b = copy.deepcopy(a)
b[2][0][0] = '555'
print(a, b)
從這個例子里可以看出來淺copy和深copy的區別:
淺copy:復制父對象,子對象仍然使用引用的方式。深copy:復制了對象和對象的所有子對象。
方法
copy.copy(x) 淺copy
copy.deepcopy(x) 深copy
淺copy和深copy的區別只與復合對象有關(對象包含其他對象,如列表或類實例)
淺copy構造了一個新的復合對象,然后(盡可能地)將原始對象的引用插入。
深copy構造了一個新的復合對象,然后遞歸地將原始對象的副本插入。
那么問題來了:遞歸的將原始對象的副本插入,如果這個列表的深度是無限的會怎么樣?
show code time
a = ['111', '222', ['333', '444', ['555', '666']]] a.append(a) def deep_copy(copy_list): b = list() for i in copy_list: if isinstance(i, list): if i is copy_list: pass else: i = deep_copy(i) if i is copy_list: b.append(b) else: b.append(i) return b c = deep_copy(a) c[2][2][0] = '777' print(a) print(c)