標籤:str 需要 append 為什麼 ruby -- 而不是 list 第一個
title: python 深拷貝和淺拷貝
tags: python,copy,deepcopy
grammar_cjkRuby: true
---
python 深拷貝和淺拷貝
python的變數的賦值都是引用
把一個變數賦值給一個變數,不是拷貝這個對象,而是拷貝這個變數的引用
直接賦值
傳遞的是這個變數的引用
淺拷貝
拷貝的是這個變數的引用,會產生新的對象
淺拷貝會產生一個新的對象,但是淺拷貝的內容還是原有對象的引用
看下面的例子
淺拷貝
import copya = [1, 2, 3, 4 ,5]b = copy.copy(a)print id(a)140637017675968print id(b)140637017452416print [id(item) for item in a][30363992, 30363968, 30363944, 30363920, 30363896]print [id(item) for item in b] [30363992, 30363968, 30363944, 30363920, 30363896]
我們可以看到,copy.copy這個淺拷貝的操作,產生了一個新的對象
因此,id(a) ,id(b)是不同的
但是,淺拷貝對於所拷貝對象中的各個元素,只會使用這些元素的引用,並不會再繼續產生新的對象
所以,兩者各個元素的id是相同的
再看個淺拷貝的例子
import copya = [1, 2, 3, 4 ,5]b = copy.copy(a)print id(a)140337638905904print id(b)140337638904824a.append(6)print a[1, 2, 3, 4, 5, 6]print id(a)140337638905904print b[1, 2, 3, 4, 5]print id(b)140337638904824
可以看到,因為淺拷貝也是建立了一個新的對象,所以a 和 a的淺拷貝b,是兩個不同的對象
所以給對象aj添加元素,並不會對b產生影響
再來看一個淺拷貝的例子 這個淺拷貝的例子對於其拷貝的對象也產生了影響,為什麼呢?
import copy a = [1, 2, 3, [1]]print id(a)140063950885808b = copy.copy(a)print id(b)140063949633512print [id(item) for item in a][29266264, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]a[3].append(2)print a[1, 2, 3, [1, 2]] print b[1, 2, 3, [1, 2]]
可以看到,這個例子中,a對象和其拷貝產生的對象b
首先,淺拷貝,建立了一個對象b
a 和 b是兩個不同的對象
由於淺拷貝,建立的對象b的各個元素其實是原對象a的各個元素的引用(這是和上一個例子不同的地方,上一個例子是原有對象新增了一個元素)
這個例子是原有對象對於其最後一個元素(也是清單類型)新增了一個元素
因為 a 和b 兩個對象的各個元素其實是一樣的(b的各個元素其實是a的各個元素的引用),所以a 的某個元素的變化會讓b一樣的變化
我們再看一個淺拷貝的例子
import copya = [1, 2, 3, [1]]print id(a)140063950885808b = copy.copy(a)print id(b)140063949633512print [id(item) for item in a][29266264, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]a[3].append(2)print a[1, 2, 3, [1, 2]]print b[1, 2, 3, [1, 2]]a[0] = 10a[10, 2, 3, [1, 2]]b[1, 2, 3, [1, 2]]print [id(item) for item in a][29266048, 29266240, 29266216, 140063949688416]print [id(item) for item in b][29266264, 29266240, 29266216, 140063949688416]
前面的操作都沒毛病,怎麼最後對於對象a的第一個元素的操作讓a變化了,卻沒有影響到b呢?
這是因為操作的a的第一個元素是int類型,這是不可變對象,對於不可變對象的重新賦值本質上是建立一個新的對象
所以,其實這樣操作後a的第一個元素對應的對象已經不是原來的對象了,當然不會影響到b
深拷貝
import copya = [1, 2, 3, 4, [1]]b = copy.deepcopy(a)print [id(item) for item in a][40378712, 40378688, 40378664, 40378640, 140313123501048]print [id(item) for item in b][40378712, 40378688, 40378664, 40378640, 140313122753568]a[4].append(2)a[1, 2, 3, 4, [1, 2]]b[1, 2, 3, 4, [1]]
在上面,我們可以看到,深拷貝,對於a 的 a[4] 即一個可變對象(list類型)而言,是產生了一個新的對象,而不是像淺拷貝一樣,只是原對象元素的引用
因此,原對象的變化,不會引起拷貝對象的變化
總結:
對於淺拷貝,深拷貝來說,如果拷貝對象的元素是不可變類型(或者說不可變對象)
則無論淺拷貝,深拷貝,對原有對象的改變,都不會影響到拷貝的對象的這個元素
因為,不可變類型的更改,其實是建立了一個對象,自然不會影響到原有對象
當被拷貝對象含有可變類型的元素的時候,對於原有對象的這個可變類型的元素的更改:
淺拷貝,會影響到被拷貝對象
深拷貝,不會影響到被拷貝對象,因為深拷貝對於不可變類型的元素,是產生了一個新的對象來複製這個元素的
所以,如果希望複製一份原有對象,不被影響,需要使用深拷貝
python深拷貝和淺拷貝之簡單分析