Python 深淺複製

Python中的賦值語句不復制對象,它們在目標和對象之間創建綁定。對於可變的或包含可變項的容器,有時需要一個副本,所以可以改變一個副本而不改變另一個。


淺複製

將創建一個新對象,但它包含的是對原始對象包含的項的引用。

a = [] 
b = list(a)
c=a.copy()
d = copy.copy(a)

深複製

創建一個新對象,並且遞歸的複製他包含的所有對象。

import copy 
b = []
a = copy.deepcopy(b)

當原始對象中包含可變對象a,淺複製僅僅複製對a的引用

這時,如果a的值更改,那麼相應新對象中a的值也會更改

>>> a=[1,2,3]
>>> b = {'x':['a','b'], 'y':a}    #字典b的value都是可變對象

>>> c = copy.copy(b)        #淺複製
>>> d = copy.deepcopy(b)    #深複製

>>> a.pop()                #修改a
3
>>> b
{'x': ['a', 'b'], 'y': [1, 2]}    #原始對象b改變
>>> c
{'x': ['a', 'b'], 'y': [1, 2]}    #淺複製c同樣發生改變
>>> d
{'x': ['a', 'b'], 'y': [1, 2, 3]}    #深複製d不變

>>> b['x'].append('c')
>>> b
{'x': ['a', 'b', 'c'], 'y': [1, 2]}
>>> c
{'x': ['a', 'b', 'c'], 'y': [1, 2]}
>>> d
{'x': ['a', 'b'], 'y': [1, 2, 3]} 

使用內置函數id()來查看對象的標識

                        標識相當於內存中對象中的地址

>>> id(a)
50285512
>>> id(b['y'])
50285512
>>> id(c['y'])        
50285512
>>> id(d['y'])
49946056

可以發現原始對象b['y']和淺複製對象c['y']的標識相同,和a引用同一個值,而深複製對象d['y']引用的是一個新的值


        所以將a添加到淺複製對象c['y']中會導致遞歸引用

>>> a
[1, 2]
>>> c['y'].append(a)
>>> c
{'x': ['a', 'b', 'c'], 'y': [1, 2, [...]]}    #c['y']出現遞歸引用
>>> a.pop()        #刪除a中對a的引用
[1, 2]
>>> d
{'x': ['a', 'b'], 'y': [1, 2, 3, [1, 2]]}    #d['y']和a引用的不是一個值,所以不會發生詆譭引用

實現簡單的深淺複製

def mycopy(x):
    '''淺複製函數,接受list,tuple,set,dict類型的參數'''
    types = {list,tuple,set}
    cls = type(x)
    if cls in types:
        n = [item for item in x]
        return cls(n)
    elif cls is dict:
        return {key:value for key,value in x.items()}
    raise TypeError






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章