天天看點

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)           

淺拷貝與深拷貝的運作結果将在下面分别呈現。

淺拷貝

解除對應注釋後,運作結果:

Python淺拷貝與深拷貝引入淺拷貝深拷貝

1)通過切片操作,工廠函數(list(),tuple(),dict())或copy子產品的copy函數産生的都是淺拷貝。

2)淺拷貝得到的兩個對象的id不同,但内容的id是相同的。若内容發生改變,不可變對象的id會變不同,彼此不影響;可變對象的id仍相同,彼此影響。

深拷貝

解除對應注釋後,運作結果:

Python淺拷貝與深拷貝引入淺拷貝深拷貝

1)使用copy子產品的deepcopy函數産生的是深拷貝。

2)深拷貝得到的兩個對象的id不同,内容中可變對象id不同,内容中不可變對象id相同。如果内容發生改變,不可變對象id變不同,彼此不影響;可變對象id仍然不同,彼此不影響。

參考自Python核心程式設計第二版6.20節;文中如有不恰當的地方,還望包容和指出,感謝