1. python如何拷貝乙個物件?
在python中如何拷貝乙個物件呢?我們很多時候會用等號賦值法,除了=賦值,實際上還有淺拷貝和深拷貝,那麼賦值,淺拷貝和深拷貝到底有什麼區別呢?
(1) 賦值(=):建立了物件的乙個新的引用,修改其中任意乙個變數都會影響到另外乙個;
(2) 淺拷貝:建立乙個新的物件,但是它包含的是對原始物件中包含項的引用(如果用引用的方式修改其中乙個物件,另外乙個也會改變),即淺拷貝只拷貝頂層引用;
(3) 深拷貝:建立乙個新物件,並且遞迴的複製它所包含的物件(修改其中乙個,另外乙個不會改變),即深拷貝會逐層進行拷貝,直到拷貝的所有引用都是不可變引用為止。
淺拷貝和深拷貝從概念上看有點抽象,我們可以通過下面的例子來說明:
2. 舉例說明
例如有列表 l1=['aaa', 66, [1, 2, 3]],l2是對l1的賦值,l3是對l1的淺拷貝,l4是對l1的深拷貝。
>>> l1 = ['aaa', 66, [1, 2, 3]]
>>> l2 = l1
>>> l3 = l1.copy()
>>> l4 = copy.deepcopy(l1)
>>> id(l1)
140214926880712 ------> 指向同一塊記憶體位址
>>> id(l2)
140214926880712 ------> 賦值是拷貝引用,指向同一塊記憶體位址
>>> id(l3)
140215054238536 ------> 建立新的物件,即分配新的記憶體位址
>>> id(l4)
140214924504200
再列印列表l1的第3個元素的id:
>>> id(l1[2])
140214926939592
>>> id(l2[2])
140214926939592 ------> 賦值後第三個元素指向[1, 2, 3]的位址 可變物件
>>> id(l3[2])
140214926939592 ------> 淺拷貝後第三個元素指向[1, 2, 3]的位址 可變物件,這就是所謂的淺拷貝,只拷貝頂層引用
>>> id(l4[2])
140214926938440 ------> 深拷貝賦值所有的內容,所以第三個元素的記憶體位址與賦值和淺拷貝均不同,這就是所謂的深拷貝,遞迴賦值
修改l1的第3個元素,檢視賦值,淺拷貝,深拷貝的列表值的變化
>>> l1[2][0] = 4
>>> l1
['aaa', 66, [4, 2, 3]]
>>> l2
['aaa', 66, [4, 2, 3]] ------> 因為賦值l2是拷貝的l1的引用,l1的元素變化l2會跟著變化
>>> l3
['aaa', 66, [4, 2, 3]] ------> 因為淺拷貝l3的第三個元素拷貝的引用,故l3的第三個元素也會變化
>>> l4
['aaa', 66, [1, 2, 3]] ------> 可以看出深拷貝並不會因為l1的變化而影響,因為深拷貝會逐層進行拷貝,直到拷貝的所有引用都是不可變引用為止
接下來在列表l1追加乙個元素,觀察賦值,淺拷貝,深拷貝的列表值的變化:
>>> l1
['aaa', 66, [4, 2, 3], 88]
>>> l2
['aaa', 66, [4, 2, 3], 88] -------> 同理因為賦值l2是拷貝的l1的引用,l1的元素變化l2會跟著變化
>>> l3
['aaa', 66, [4, 2, 3]] -------> 到這裡應該就容易理解了吧,因為淺拷貝l3的記憶體是新分配的,故l1追加元素並不會影響淺拷貝l3的值
>>> l4
['aaa', 66, [1, 2, 3]] -------> 和我們預期的一樣,深拷貝依然不受影響
在這裡補充下例子中的淺拷貝,在python中一切皆是物件,通過概念我們可以看出淺拷貝是建立了乙個新的物件,但是這個新物件中的內容仍然是指向原始物件中包含項的引用,可以理解為淺拷貝是新物件,但是物件的包含項仍然是舊的引用。所以上面例子中,l1[2][0] =4 修改列表l1後淺拷貝的第3個元素會隨著l1的改變而變化,因為[1,2,3]本身就是個可變的列表,其在初始化時記憶體位址已經分配好,這個把記憶體位址拷貝給了l3;而 l1.aapend(88)執行後l3列表並沒有追加該元素,因為l3是個物件,是個新物件,與l1的記憶體位址不同,所以不會受影響。不知道我這裡有沒有講清楚。
3. 總結:
賦值:預設淺拷貝傳遞物件的引用而已,原始列表改變,被賦值的b也會做相同的改變;
淺拷貝:沒有拷貝子物件,所以原始資料改變,子物件會改變
深拷貝:包含物件裡面的子物件的拷貝,所以原始物件的改變不會造成深拷貝裡任何子元素的改變
在其他帖子看到對淺拷貝和深拷貝這樣的總結,挺有意思的:
淺拷貝就是藕斷絲連 ----只拷貝頂層引用,子項還存在引用關係
深拷貝就是離婚了 ----徹底沒關係了
為什麼python預設的拷貝方式是淺拷貝?
時間角度:淺拷貝花費時間更少;
空間角度:淺拷貝花費記憶體更少;
效率角度:淺拷貝只拷貝頂層資料,一般情況下比深拷貝效率高。
python 深拷貝 Python深拷貝和淺拷貝!
在python中,物件賦值實際上是物件的引用。當建立乙個物件,然後把它賦給另乙個變數的時候,python並沒有拷貝這個物件,而只是拷貝了這個物件的引用 一般有三種方法,alist 1,2,3,a b 1 直接賦值 b alist,預設淺拷貝傳遞物件的引用而已,原始列表改變,被賦值的b也會做相同的改變...
Python 深拷貝和淺拷貝
淺拷貝只拷貝了引用,並沒有拷貝內容,相當於把原來的引用複製了乙份給新的變數 深拷貝是將原來的值複製了乙份到新的地方 in 30 a 1,2,3 in 31 b a in 32 id a out 32 140618626865352 in 33 id b out 33 140618626865352 ...
python深拷貝和淺拷貝
copy.copy 淺拷貝 只拷貝父物件,不會拷貝物件的內部的子物件。比深拷貝更加節省記憶體 copy.deepcopy 深拷貝 拷貝物件及其子物件 用乙個簡單的例子說明如下 import copy公升 a 1,2,3,4,a b c b a c copy.copy a d copy.deepcop...