Python淺拷貝與深拷貝

從字面意思理解,拷貝即複製當前的對象。但是只有在容器對象(列表,元組,字典)纔有拷貝這一概念,原子對象(數字,字符串)沒有拷貝這一說


引入


普通的複製都是淺拷貝。
淺拷貝可以理解爲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節;文中如有不恰當的地方,還望包容和指出,感謝


發佈了56 篇原創文章 · 獲贊 105 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章