最近遇到了一個問題,在python中對於對象的複製有兩種,copy()以及deepcopy(),爲了研究他們之間的區別,寫下以下博客。
首先查看python的官方文檔,獲得以下解釋:python
淺層複製和深層複製之間的區別僅與複合對象 (即包含其餘對象的對象,如列表或類的實例) 相關: 一個 淺層複製 會構造一個新的複合對象,而後(在可能的範圍內)將原對象中找到的 引用 插入其中。 一個 深層複製 會構造一個新的複合對象,而後遞歸地將原始對象中所找到的對象的 副本 插入。
爲了明白其中的原理,作了以下實驗:code
簡單對象是指不包含子對象的對象,也就是隻包含普通元素(數字,字符串)的對象,對於簡單對象,copy與deepcopy方法沒有什麼區別,下面的一段代碼,能夠先看一下效果是怎樣的。對象
import copy if __name__ == '__main__': a = [1, 2, 3, 4] b = copy.copy(a) c = copy.deepcopy(a) print(a == b) print(a is b) print(a == c) print(a is c)
執行上面的代碼,咱們能夠看到執行結果,深複製和淺複製的執行結果是同樣的遞歸
True # 說明 a 和 b 所指向的對象的內容相同 False # 說明 a 和 b 所指向的不是同一個對象(地址不一樣) True # 說明 a 和 c 所指向的對象的內容相同 False # 說明 a 和 c 所指向的不是同一個對象(地址不一樣)
能夠用一張圖來解釋一下,爲何簡單對象的深淺複製是同樣的。內存
咱們知道,上面的圖中,變量a指向一個List對象(或者說是一個List對象的引用),該對象在內存中佔用一個地址空間,當簡單對象執行copy和deepcopy中的對象時,咱們能夠看到不管時深複製仍是淺複製,都是在內存中新開闢一個地址空間,將原來對象中的內容複製過去,同時讓b成爲新對象的引用。所以,咱們看到a和b指向的對象是不一致的,可是內容是相同的。文檔
複雜對象能夠理解爲另外包含其餘簡單對象的對象,也就是包含子對象的對象,例如:List中嵌套List,或者Dict中嵌套List等,對於複雜對象咱們先來看一個簡單的程序示例。字符串
import copy if __name__ == '__main__': a = {'name': 'test', 'age': 56, 'address': [1, 2, 3, 4, 5]} b = copy.copy(a) print(a is b) print(a['address'] is b['address']) c = copy.deepcopy(a) print(a is c) print(a['address'] is c['address'])
執行結果以下:博客
False # 說明 a 和 b 不是同一個對象的引用 True # 說明 a中的address 和 b 中的 address 是同一個對象。黑人問號臉?? False # 說明 a 和 c 不是同一個對象的引用 False # 說明 a中的address 和 c 中的 address 不是同一個對象
下面我經過一張圖,來大概解釋一下爲何會出現上面的結果。PS:具體對象的對象不必定是按照圖中的方式,爲了可以說明原理,本圖中將子對象的存儲空間單獨抽出,方便理解。class
咱們看到對於複雜對象(包含子對象的對象)的複製,深淺複製在實現原理上就有所不一樣了。經過上圖咱們能夠看到,複雜對象的深淺複製的區別在於複雜對象的子對象。能夠看到:test