1. 程式人生 > >從底層分析python中深拷貝和淺拷貝區別

從底層分析python中深拷貝和淺拷貝區別

深淺拷貝在python中經常使用,其區別的外在表現是:

使用淺拷貝,當原容器物件中可變物件中有元素髮生變化,拷貝得到的物件也會變化。而使用深拷貝時,不會有這種問題。

聽起來有一點難理解,看例子比較直觀:

淺拷貝

>>> list1 = [['a', 'b'], 1, 2]

>>> list3 = copy.copy(list1)

>>> list3

[['a', 'b'], 1, 2]

>>> list1[0][0] = 'c' #修改lsit1

>>> list3

[['c', 'b'], 1, 2] #list3也變了

深拷貝

>>> list1 = [['a', 'b'], 1, 2]

>>> list3 = copy.deepcopy(list1)

>>> list1[0][0] = 'c' #修改list1

>>> list3

[['a', 'b'], 1, 2] #list3沒有變

但是為什麼會這樣,可以由下圖解釋:


當我們宣告list1 = [['a', 'b'], 1, 2]時,計算機做了這些事:

1、在記憶體中開闢一段空間,用來存放字元a,b和數字1,數字2

2、在記憶體開闢一段空間,用來存放一個列表,我們稱為list2。list2中存放兩個指標,分別指向字元a和b

3、在記憶體開闢一段空間,用來存放一個列表lsit1,list1中存放三個指標,分別指向list2,數字1和數字2

當執行淺拷貝lsit3 = copy.copy(list1)時,計算機開闢一段記憶體給list3,list3儲存三個指標,分別指向list2,數字1和數字2。當執行list1[0][0] = 'c'時,list2物件修改了,而list3的第一個指標指向list2,所以我們看到list3的第一個元素也變了。

當執行深拷貝lsit4 = copy.copy(list1)時,計算機開闢一段記憶體給list4,和淺拷貝不同的是,計算機同時開闢一段空間給新的列表,我們稱為lsit5。list5中儲存2個指標,分別指向字元a和b。

同時list4儲存三個指標,分別指向list5,數字1和數字2。此時,當執行list1[0][0] = 'c'時,list2物件修改了,但list4的第一個指標指向list5,list5並沒有修改,所以list4沒有改變。

總結:深拷貝會把可變物件也拷貝一份,而淺拷貝不會。

上面例子中說的是列表(可變物件)的拷貝,那對於元組,字元等不可不物件呢?

答案是,對不可不物件,其實不存在深淺拷貝的問題。無論怎麼拷貝,效果都是新建立一個指向不可變物件的指標而已。

>>> a = 'f'

>>> b = copy.copy(a)

>>> id(a)

4302389968

>>> id(b)

4302389968

>>> c = copy.deepcopy(a)

>>> id(c)

4302389968

>>> 

>>> d = a

>>> id(a)

4302389968