深淺copy,何為深淺copy,深copy和淺copy兩者有何不同


copy,拷貝,顧名思義,自然是把東西復制過來,呈現在眼前的是一樣的,例如:

a = [1,2,3,4,5]
b = a
b.append(6)
print(a,b)

 輸出:

[1, 2, 3, 4, 5, 6] [1, 2, 3, 4, 5, 6]

 

很明顯,a和b的值是一樣的。因為對於賦值運算來講,a與b指向的是同一內存地址,所以他們完全是一樣的

 

淺copy:

a = [1,2,3,4,[5]]
b = copy.copy(a)
b[4].append(6)
print(a)
print(b)

print(id(a))
print(id(b))

print(id(a[0]))
print(id(b[0]))

print(id(a[4]))
print(id(b[4]))

輸出:

[1, 2, 3, 4, [5, 6]]
[1, 2, 3, 4, [5, 6]]
3123924048968
3123924049032
140709039403264
140709039403264
3123924285128
3123924285128

 

可以看到,a和b的輸出地址不一樣,原因是對於淺copy來說,只是在內存中重新創建了開辟了一個空間存放一個新列表,但是新列表中的元素與原列表中的元素是公用的,且元素原地址一樣不變。

但我們如果對它進行增刪改,兩者是否會相互改變呢?

從上面看,列表當中的可變數據類型進行增加元素時,兩者是會相互影響的,且地址一直一致;

但從下面看,對列表當中的不可變數據類型進行修改時,雖然元素地址一樣,但兩者是不會相互影響,並且經過修改后,元素地址發生改變,兩者地址變得不一樣。

import copy
a = [1,2,3,4,[5]]
b = copy.copy(a)
b[0] = 0
print(a)
print(b)
print(id(a[0])) print(id(b[0]))

 

輸出:

[1, 2, 3, 4, [5]]
[0, 2, 3, 4, [5]]
140709362168064
140709362168032

 

 

而在整個列表添加新的元素時,兩者同樣不會相互影響,只要copy過來的元素不發生改變,元素地址會一直保持一致

import copy
a = [1,2,3,4,[5]]
b = copy.copy(a)
b.append(8)

print(a)
print(b)

print(id(a[0]))
print(id(b[0]))

 

 輸出:

[1, 2, 3, 4, [5]]
[1, 2, 3, 4, [5], 8]
140709362168064
140709362168064

 

 

所以得出結論是,淺copy時,內存會開辟一個新的空間存放一個新的列表,所以地址不一致。列表中的元素和元素地址都會被copy過來,而可變數據類型(列表中的列表,二級列表)被當作一個整體不被拷貝,所以地址永遠一致,對可變數據類型中的元素改變時,a和b會相互影響,元素永遠相同。

而一級列表中的不可變數據類型,雖然元素與地址都被復制過來,但兩者進行修改時不會相互影響,並且修改后地址會變得不一致。而在一級列表添加新的元素時,兩者同樣不會相互影響,只要不改變copy過來的元素,地址會一直與copy過來的一致。

 

深copy:

import copy
a = [1,2,3,4,[5]]
b = copy.deepcopy(a)
b[4].append(6)
print(a)
print(b)

print(id(a))
print(id(b))

print(id(a[0]))
print(id(b[0]))

print(id(a[4]))
print(id(b[4]))

 

輸出:

[1, 2, 3, 4, [5]]
[1, 2, 3, 4, [5, 6]]
1861657304264
1861657304328
140709043532032
140709043532032
1861657540168
1861657304456

它是拷貝所有內容。包括內部(列表的列表)的所有,形成一個新的對象,雖然與之前的值和內容一模一樣,但是它們時完完全全的兩個對象,所以不僅a和b的地址不同,可變數據類型的地址同樣被拿出來存在新的內存當中,地址同樣會不一樣,所以做出改變時不會相互影響;其它與淺copy一致,不可變數據類型改變時不會相互影響,且改變后地址會發生改變;

 

注:

當切片進行賦值時,兩者地址會不一樣,並且進行增刪改時,兩者互不影響:

a = [1,2,3,4,5]
b = a[0::]
b.pop(0)
print(a)
print(b)
print(id(a))
print(id(b))

 

輸出:

[1, 2, 3, 4, 5]
[2, 3, 4, 5]
2525473650376
2525473414152

 

 

僅存在一種情況,兩者相互影響且地址永遠一致:

a = [1,2,3,4,5]
b = a
b.append(6)
a.pop(2)
print(a)
print(b)
print(id(a))
print(id(b))

 

輸出:

[1, 2, 4, 5, 6]
[1, 2, 4, 5, 6]
2957431125704
2957431125704

 

 

以上測試基於python3.7.4

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM