淺拷貝、深拷貝的區別
一,淺拷貝:建立一個新的物件,但它包含的是對原始物件中包含項的引用(如果用引用的方式修改 其中一個物件,另外一個也會修改改變){1,完全切片方法;2,工廠函式,如 list();3,copy 模組 的 copy()函式}。
1.1 不可變物件的拷貝
因為不可變物件只有在修改時才會開闢新空間,所以拷貝也相當於讓多個引用同時引用了一個數據,所以不可變物件的淺拷貝和賦值沒有區別
import copy a = '1' b = copy.copy(a) print(id(a), id(b))
1.2 可變物件的拷貝
對不可變物件進行賦值時,物件引用並沒有發生變化,那不可變物件拷貝時會不會相同呢?
import copy # 建立一個可變物件 l1 = [1, 2, 3] # 拷貝 l1 物件,生成副本 l2 l2 = copy.copy(l1) # l1 和 l2 的值完全相同 print(l1, l2) # 但是 l1 和 l2 的引用不同,說明拷貝成功 print(id(l1), id(l2)) # 華麗的分割線 print('*'*20) # 修改 l1 中的資料 l1[0] = 11 # l1 修改後, l2確實沒有隨著發生變化 print(l1, l2) print(id(l1), id(l2))
1.3 淺拷貝的幾種方式
在Python中,有多種方式可以實現淺拷貝 1. copy 模組的 copy 方法
import copy a = [1, 2] l1 = [3, 4, a] l2 = copy.copy(l1) print(l1, l2) print(id(l1), id(l2)) print('*'*20) a[0] = 11 print(l1, l2) print(id(l1), id(l2))
2. 物件本身的 copy 方法
a = [1, 2] l1 = [3, 4, a] l2 = l1.copy() print(l1, l2) print(id(l1), id(l2)) print('*'*20) a[0] = 11 print(l1, l2) print(id(l1), id(l2))
******************** [3, 4, [11, 2]] [3, 4, [11, 2]] 4364204936 4364205192
3. 工廠方法
a = [1, 2] l1 = [3, 4, a] l2 = list(l1) print(l1, l2) print(id(l1), id(l2)) print('*'*20) a[0] = 11 print(l1, l2) print(id(l1), id(l2))
4. 切片
a = [1, 2] l1 = [3, 4, a] l2 = l1[1:] print(l1, l2) print(id(l1), id(l2)) print('*'*20) a[0] = 11 print(l1, l2) print(id(l1), id(l2))
二,深拷貝:建立一個新的物件,並且遞迴的複製它所包含的物件(修改其中一個,另外一個不會改 變){copy 模組的 copy.deepcopy()函式}。
import copy # 建立一個可變物件a a = [1, 2] # 建立一個可變物件 l1 中包含可變物件 a l1 = [3, 4, a] # 拷貝 l1 物件,生成副本 l2 l2 = copy.deepcopy(l1) # l1 和 l2 的值完全相同 print(l1, l2) # l1 和 l2 的引用不同,說明拷貝成功 print(id(l1), id(l2)) # 華麗的分割線 print('*'*20) # 修改 a 中的資料 a[0] = 11 # a中的資料修改後, 因為l2 逐層的拷貝了所有的引用,所以l2不會發生變化 print(l1, l2) print(id(l1), id(l2))
# 以上列印地址結果,請自行動手測試。