1. 程式人生 > >淺複製和深複製

淺複製和深複製

Python中,複製有以下幾種方法

1.賦值複製

>>>a = [1, 2, 3]
>>>b = a
>>>b
[1, 2, 3]

此時的複製,b僅僅是指向了a所在的記憶體空間,在記憶體中,並沒有申請一處新的空間來儲存列表b,a和b在記憶體中的id是相同的,如果a發生改變,b也會跟著改變。

>>>id(a)
2604172565640
>>>id(b)
2604172565640
>>>
>>>a.append(4)
>>>a
[1, 2, 3, 4]
>>>b
[1, 2, 3, 4]

賦值複製,存在一種特殊情況,a1 = a * 1 , 也可以實現淺複製,此時a和a1在不同的記憶體地址,a中元素改變,a1不變,但是,如果a中存在子列表,子列表中還是指向原地址,a中子列表改變,a1中的子列表跟著改變。

>>>a1 = a * 1
>>>a1

>>>id(a1)
2604172509960
>>>id(a)
2604172565640

2.切片複製(僅適用於可切片的的物件)(淺複製)

利用列表的可以切片的特性,把列表的所有元素切片,賦值給c,間接達到複製的目的;此時在系統在記憶體中新申請了一片記憶體,用來你存放c。a改變,不影響c。

>>>a.append([5])
>>>a 
[1, 2, 3, 4, [5]]
>>>c = a[:]
>>>c
[1, 2, 3, 4, [5]]
>>>id(c)
2604172381000
>>>a.append(6)
>>>a
[1, 2, 3, 4, [5], 6]
>>>c
[1, 2, 3, 4, [5]]

此時,也僅僅是複製了頂層記憶體地址,如果存在子列表,子列表中還是指向原地址。

>>>a[4].append(1)
>>>a
[1, 2, 3, 4, [5, 1], 6]
>>>c
[1, 2, 3, 4, [5, 1]]

>>>id(a[4])
2604172564808
>>>id(c[4])
2604172564808

3.使用copy模組中的函式

      1)copy.copy()  淺複製 ,複製了目標的頂層物件,記憶體id不同,a中新增元素,d不變。

>>>import copy
>>>d = copy.copy(a)
>>>d
[1, 2, 3, 4, [5, 1], 6]
>>>id(d)
2604172700552
>>>id(a)
2604172565640

# a改變,d不變
>>>a.append(7)
>>>a
[1, 2, 3, 4, [5,1], 6, 7]
>>>d
[1, 2, 3, 4, [5, 1], 6]

但是,當a中存在子列表時,子列表中元素髮生改變,d中的子列表會跟著改變,因為copy.copy()僅複製了頂層資料的記憶體地址,並沒有複製下層子列表中元素的記憶體地址;子列表中的元素,指向同一片記憶體空間。

>>>a[4].append(7)
>>>a
[1, 2, 3, 4, [5, 1 , 7], 6, 7]
>>>d
[1, 2, 3, 4, [5, 1, 7], 6]

>>>id(a[4])
1984975808
>>>id(d[4])
1984975808

        2)copy.deepcopy() 深複製,從頂層到底層,所有的全部複製,和原資料除了值相等,沒有其他任何關係。a中子列表內元素改變,對深複製的e沒影響

>>>e = copy.deepcopy(a)
>>>e
[1, 2, 3, 4, [5, 1 , 7], 6, 7]
>>>id(a)
2604172565640
>>>id(e)
2604172381576

>>>a[4].append(8)
>>>a
[1, 2, 3, 4, [5, 1 , 7, 8], 6, 7]
>>>e
[1, 2, 3, 4, [5, 1 , 7], 6, 7]

>>>id(a[4])
2604172564808
>>>id(e[4])
2604172831240