成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

python深拷貝與淺拷貝

ideaa / 513人閱讀

摘要:之前關(guān)于的作用域賦值參數(shù)傳遞,我們接連談了幾篇文章全菊變量和菊部變量關(guān)于函數(shù)參數(shù)傳遞,人都錯(cuò)了可變對(duì)象與不可變對(duì)象今天我們依然要就相關(guān)話題繼續(xù)下去。這是由于它們是不可變對(duì)象,不存在被修改的可能,所以拷貝和賦值是一樣的。

之前關(guān)于 Python 的作用域、賦值、參數(shù)傳遞,我們接連談了幾篇文章:

全菊變量和菊部變量

關(guān)于函數(shù)參數(shù)傳遞,80%人都錯(cuò)了

可變對(duì)象與不可變對(duì)象

今天我們依然要就相關(guān)話題繼續(xù)下去。

首先是上次最后的思考題:


m = [1, 2, [3]]
n = m[:]
n[1] = 4
n[2][0] = 5
print(m)

m 的結(jié)果是什么?

正確答案是 [1, 2, [5]] ,這次比上次好點(diǎn),有 35% 的正確率。

當(dāng)時(shí)我留了個(gè)提示,說和淺拷貝、深拷貝有關(guān),現(xiàn)在我們就來具體說一說。

假設(shè)有這樣一個(gè) list 變量 m,其中有 4 個(gè)元素(別被嵌套迷惑了):


m = [1, 2, [3, 4], [5, [6, 7]]]

為了更直觀的表示,我來畫個(gè)圖:

現(xiàn)在我們想要再來“復(fù)制”一個(gè)同樣的變量。也許第一個(gè)閃過腦中的念頭就是:


n = m

但看了前面的文章后你應(yīng)該知道,這樣的 賦值只相當(dāng)于增加了一個(gè)標(biāo)簽,并沒有新的對(duì)象產(chǎn)生

id 驗(yàn)證下就知道, m 和 n 仍然是同一個(gè)東西 。那么他們內(nèi)部的元素自然也是一樣的,對(duì)其中一個(gè)進(jìn)行修改,另一個(gè)也會(huì)跟著變:


m = [1, 2, [3, 4], [5, [6, 7]]]
print("m:", id(m))
print([id(i) for i in m])
n = m
print("n:", id(n))
print([id(i) for i in n])
print(n is m)
print(n[0] is m[0])
print(n[2] is m[2])
n[0] = -1
print(m)
n[2][1] = -1
print(m)

輸出


m: 4564554888
[4556507504, 4556507536, 4564554760, 4564555016]
n: 4564554888
[4556507504, 4556507536, 4564554760, 4564555016]
True
True
True
[-1, 2, [3, 4], [5, [6, 7]]]
[-1, 2, [3, -1], [5, [6, 7]]]

因此有人將此操作稱為“ 舊瓶裝舊酒 ”,只是多貼了一層標(biāo)簽,這不能達(dá)到我們的目的。要得到一個(gè)對(duì)象的“拷貝”,我們需要用到 copy 方法:


from copy import copy
m = [1, 2, [3, 4], [5, [6, 7]]]
print("m:", id(m))
print([id(i) for i in m])
n = copy(m)
print("n:", id(n))
print([id(i) for i in n])
print(n is m)
print(n[0] is m[0])
print(n[2] is m[2])
n[0] = -1
print(m)
n[2][1] = -1
print(m)

輸出


m: 4340253832
[4333009264, 4333009296, 4340253704, 4340253960]
n: 4340268104
[4333009264, 4333009296, 4340253704, 4340253960]
False
True
True
[1, 2, [3, 4], [5, [6, 7]]]
[1, 2, [3, -1], [5, [6, 7]]]

從結(jié)果中可以看出, n 和 m 已不是同一個(gè)對(duì)象 ,對(duì)于某個(gè)元素的重新賦值不會(huì)影響原對(duì)象。但是,它們 內(nèi)部的元素全都是一樣的 ,所以對(duì)一個(gè)可變類型元素的修改,則仍然會(huì)反應(yīng)在原對(duì)象中。

(其實(shí)這里1、2也是指向同一個(gè)對(duì)象,但作為不可變對(duì)象來說,它們互不影響,直觀上的感受就相當(dāng)于是復(fù)制了一份,故簡(jiǎn)化如圖上所示)

這種復(fù)制方法叫做 淺拷貝shallow copy ),又被人形象地稱作“ 新瓶裝舊酒 ”,雖然產(chǎn)生了新對(duì)象,但里面的內(nèi)容還是來自同一份。

如果要徹底地產(chǎn)生一個(gè)和原對(duì)象完全獨(dú)立的復(fù)制品,得使用 深拷貝deep copy ):


from copy import deepcopy
m = [1, 2, [3, 4], [5, [6, 7]]]
print("m:", id(m))
print([id(i) for i in m])
n = deepcopy(m)
print("n:", id(n))
print([id(i) for i in n])
print(n is m)
print(n[0] is m[0])
print(n[2] is m[2])
n[0] = -1
print(m)
n[2][1] = -1
print(m)

輸出


m: 4389131400
[4381886832, 4381886864, 4389131272, 4389131528]
n: 4389131208
[4381886832, 4381886864, 4389131656, 4389145736]
False
True
False
[1, 2, [3, 4], [5, [6, 7]]]
[1, 2, [3, 4], [5, [6, 7]]]

此時(shí), 對(duì)新對(duì)象中元素做任何改動(dòng)都不會(huì)影響原對(duì)象 。新對(duì)象中的子列表,無論有多少層,都是新的對(duì)象,有不同的地址。

按照前面的比喻,深拷貝就是“ 新瓶裝新酒 ”。

你可能會(huì)注意到一個(gè)細(xì)節(jié):n 中的前兩個(gè)元素的地址仍然和 m 中一樣。這是由于它們是 不可變對(duì)象,不存在被修改的可能,所以拷貝和賦值是一樣的

于是,深拷貝也可以理解為,不僅是對(duì)象自身的拷貝,而且對(duì)于對(duì)象中的每一個(gè)子元素,也都進(jìn)行同樣的拷貝操作。這是一種 遞歸 的思想。

不過額外要說提醒一下的是, 深拷貝的實(shí)現(xiàn)過程并不是完全的遞歸 ,否則如果對(duì)象的某級(jí)子元素是它自身的話,這個(gè)過程就死循環(huán)了。實(shí)際上, 如果遇到已經(jīng)處理過的對(duì)象,就會(huì)直接使用其引用,而不再重復(fù)處理 。聽上去有點(diǎn)難懂是不是?想想這個(gè)例子大概就會(huì)理解了:


from copy import deepcopy
m = [1, 2]
m.append(m)
print(m, id(m), id(m[2]))
n = deepcopy(m)
print(n, id(n), id(n[2]))

輸出


[1, 2, [...]] 4479589576 4479589576
[1, 2, [...]] 4479575048 4479575048

最后,還是給各位留個(gè)思考:


from copy import deepcopy
a = [3, 4]
m = [1, 2, a, [5, a]]
n = deepcopy(m)
n[3][1][0] = -1
print(n)

深拷貝后的 n,修改了其中一個(gè)元素值,會(huì)是怎樣的效果?

思考一下輸出會(huì)是什么?

然后自己在電腦上或者我們的在線編輯器 Crossin的編程教室 - 在線Python編輯器 里輸入代碼運(yùn)行下看看結(jié)果,再想想為什么。

歡迎留言給出你的解釋。

════

其他文章及回答:

如何自學(xué)Python | 新手引導(dǎo) | 精選Python問答 | Python單詞表 | 人工智能 | 嘻哈 | 爬蟲 | 我用Python | 高考 | requests | AI平臺(tái)

歡迎搜索及關(guān)注: Crossin的編程教室

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44991.html

相關(guān)文章

  • python 拷貝與淺拷貝

    摘要:深拷貝和淺拷貝原始對(duì)象賦值,傳對(duì)象的引用對(duì)象拷貝,淺拷貝對(duì)象拷貝,深拷貝修改對(duì)象修改對(duì)象中的數(shù)組對(duì)象 深拷貝和淺拷貝 import copy a = [1, 2, 3, 4, [a, b]] #原始對(duì)象 b = a #賦值,傳對(duì)象的引用 c = copy.copy(a) #對(duì)象拷貝,淺拷貝 d = copy.deepcopy(a) #對(duì)象拷貝,深拷貝 a...

    JeOam 評(píng)論0 收藏0
  • 面試篇---1 如何區(qū)分拷貝與淺拷貝

    摘要:引用數(shù)據(jù)類型名存在棧內(nèi)存中,值存在于堆內(nèi)存中,但是棧內(nèi)存會(huì)提供一個(gè)引用的地址指向堆內(nèi)存中的值,我們以上面淺拷貝的例子畫個(gè)圖當(dāng)進(jìn)行拷貝時(shí),其實(shí)復(fù)制的是的引用地址,而并非堆里面的值。 如何區(qū)分深拷貝與淺拷貝? 簡(jiǎn)單來說,就是假設(shè)B復(fù)制了A,當(dāng)修改A時(shí),看B是否會(huì)發(fā)生變化,如果B也跟著變了,說明這是淺拷貝,拿人手短,如果B沒變,那就是深拷貝,自食其力。 淺拷貝例子: var a=[0,1...

    jsdt 評(píng)論0 收藏0
  • JS中的拷貝與淺拷貝

    摘要:中的深拷貝與淺拷貝說到深淺拷貝的時(shí)候就不得不說一下中的變量類型了基本類型按值存放在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段可以直接訪問引用類型存放在堆內(nèi)存中的對(duì)象變量保存的是一個(gè)指向存放數(shù)據(jù)位置的指針訪問引用類型的值時(shí)首先從棧中獲取到存放該數(shù)據(jù)位置的指針然后再 JS中的深拷貝與淺拷貝 說到深淺拷貝的時(shí)候就不得不說一下JS中的變量類型了: 基本類型: undefined、null、boolean、numb...

    ARGUS 評(píng)論0 收藏0
  • 談?wù)?em>深拷貝與淺拷貝

    摘要:前言關(guān)于深拷貝和淺拷貝其實(shí)是兩個(gè)比較基礎(chǔ)的概念,但是我還是想整理一下,因?yàn)槔锩嬗泻芏嘈〖?xì)節(jié)還是很有意思的。那深拷貝就是兩者指向不同的內(nèi)存地址,是真正意義上的拷貝。談?wù)勈俏覀兘?jīng)常用到的方法,其實(shí)這個(gè)方法就是淺拷貝。 前言 關(guān)于深拷貝和淺拷貝其實(shí)是兩個(gè)比較基礎(chǔ)的概念,但是我還是想整理一下,因?yàn)槔锩嬗泻芏嘈〖?xì)節(jié)還是很有意思的。 深拷貝和淺拷貝的區(qū)別 深拷貝和淺拷貝是大家經(jīng)常聽到的兩個(gè)名詞,兩...

    Awbeci 評(píng)論0 收藏0
  • JS每日一題:拷貝與淺拷貝的區(qū)別?如何實(shí)現(xiàn)一個(gè)拷貝

    摘要:期深拷貝與淺拷貝的區(qū)別如何實(shí)現(xiàn)一個(gè)深拷貝在回答這個(gè)問題前,我們先來回顧一下中兩大數(shù)據(jù)類型基本類型引用類型基本類型基本類型就是值類型存放在棧內(nèi)存中的簡(jiǎn)單數(shù)據(jù)段,數(shù)據(jù)大小確定,內(nèi)存空間大小可以分配引用類型引用類型存放在堆內(nèi)存中的對(duì)象,變量實(shí)際保 20190311期 深拷貝與淺拷貝的區(qū)別?如何實(shí)現(xiàn)一個(gè)深拷貝 在回答這個(gè)問題前,我們先來回顧一下JS中兩大數(shù)據(jù)類型 基本類型 Undefined...

    MiracleWong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<