淺複製和深複製
阿新 • • 發佈:2018-11-08
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