Python-copy()與deepcopy()區(qū)別

copy()與deepcopy()之間的區(qū)分必須要涉及到python對于數(shù)據(jù)的存儲方式傅物。

首先直接上結論:
—–我們尋常意義的復制就是深復制顷链,即將被復制對象完全再復制一遍作為獨立的新個體單獨存在目代。所以改變原有被復制對象不會對已經(jīng)復制出來的新對象產(chǎn)生影響。
—–而淺復制并不會產(chǎn)生一個獨立的對象單獨存在嗤练,他只是將原有的數(shù)據(jù)塊打上一個新標簽榛了,所以當其中一個標簽被改變的時候,數(shù)據(jù)塊就會發(fā)生變化煞抬,另一個標簽也會隨之改變霜大。這就和我們尋常意義上的復制有所不同了。

對于簡單的 object革答,用 shallow copy 和 deep copy 沒區(qū)別
復雜的 object战坤, 如 list 中套著 list 的情況遮婶,shallow copy 中的 子list,并未從原 object 真的「獨立」出來湖笨。也就是說旗扑,如果你改變原 object 的子 list 中的一個元素,你的 copy 就會跟著一起變慈省。這跟我們直覺上對「復制」的理解不同臀防。

>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里邊有三個元素:1, 2边败,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2
True
>>> cop1 is cop2
False 
#cop1 和 cop2 看上去相同袱衷,但已不再是同一個object
>>> origin[2][0] = "hey!" 
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]
#把origin內(nèi)的子list [3, 4] 改掉了一個元素,觀察 cop1 和 cop2

可以看到 cop1笑窜,也就是 shallow copy 跟著 origin 改變了致燥。而 cop2 ,也就是 deep copy 并沒有變排截。
似乎 deep copy 更加符合我們對「復制」的直覺定義: 一旦復制出來了嫌蚤,就應該是獨立的了。如果我們想要的是一個字面意義的「copy」断傲,那就直接用 deep_copy 即可脱吱。
那么為什么會有 shallow copy 這樣的「假」 copy 存在呢? 這就是有意思的地方了认罩。

python的數(shù)據(jù)存儲方式

Python 存儲變量的方法跟其他 OOP 語言不同箱蝠。它與其說是把值賦給變量,不如說是給變量建立了一個到具體值的 reference垦垂。
當在 Python 中 a = something 應該理解為給 something 貼上了一個標簽 a宦搬。當再賦值給 a 的時候,就好象把 a 這個標簽從原來的 something 上拿下來劫拗,貼到其他對象上间校,建立新的 reference。 這就解釋了一些 Python 中可能遇到的詭異情況:

>> a = [1, 2, 3]
>>> b = a
>>> a = [4, 5, 6] //賦新的值給 a
>>> a
[4, 5, 6]
>>> b
[1, 2, 3]
# a 的值改變后杨幼,b 并沒有隨著 a 變

>>> a = [1, 2, 3]
>>> b = a
>>> a[0], a[1], a[2] = 4, 5, 6 //改變原來 list 中的元素
>>> a
[4, 5, 6]
>>> b
[4, 5, 6]
# a 的值改變后撇簿,b 隨著 a 變了

上面兩段代碼中,a 的值都發(fā)生了變化差购。區(qū)別在于,第一段代碼中是直接賦給了 a 新的值(從 [1, 2, 3] 變?yōu)?[4, 5, 6])汉嗽;而第二段則是把 list 中每個元素分別改變欲逃。
而對 b 的影響則是不同的,一個沒有讓 b 的值發(fā)生改變饼暑,另一個變了稳析。怎么用上邊的道理來解釋這個詭異的不同呢洗做?
首次把 [1, 2, 3] 看成一個物品。a = [1, 2, 3] 就相當于給這個物品上貼上 a 這個標簽彰居。而 b = a 就是給這個物品又貼上了一個 b 的標簽诚纸。

第一種情況:

a = [4, 5, 6] 就相當于把 a 標簽從 [1 ,2, 3] 上撕下來,貼到了 [4, 5, 6] 上陈惰。
在這個過程中畦徘,[1, 2, 3] 這個物品并沒有消失。 b 自始至終都好好的貼在 [1, 2, 3] 上抬闯,既然這個 reference 也沒有改變過井辆。 b 的值自然不變。


第二種情況:

a[0], a[1], a[2] = 4, 5, 6 則是直接改變了 [1, 2, 3] 這個物品本身溶握。把它內(nèi)部的每一部分都重新改裝了一下杯缺。內(nèi)部改裝完畢后,[1, 2, 3] 本身變成了 [4, 5, 6]睡榆。
而在此過程當中萍肆,a 和 b 都沒有動,他們還貼在那個物品上胀屿。因此自然 a b 的值都變成了 [4, 5, 6]匾鸥。
搞明白這個之后就要問了,對于一個復雜對象的淺copy碉纳,在copy的時候到底發(fā)生了什么勿负?
再看一段代碼:

>>> import copy
>>> origin = [1, 2, [3, 4]]
#origin 里邊有三個元素:1, 2劳曹,[3, 4]
>>> cop1 = copy.copy(origin)
>>> cop2 = copy.deepcopy(origin)
>>> cop1 == cop2
True
>>> cop1 is cop2
False 
#cop1 和 cop2 看上去相同奴愉,但已不再是同一個object
>>> origin[2][0] = "hey!" 
>>> origin
[1, 2, ['hey!', 4]]
>>> cop1
[1, 2, ['hey!', 4]]
>>> cop2
[1, 2, [3, 4]]
#把origin內(nèi)的子list [3, 4] 改掉了一個元素,觀察 cop1 和 cop2

我們可以把鏡像的概念套用在copy上面铁孵。
概念圖如下:



copy對于一個復雜對象的子對象并不會完全復制锭硼,什么是復雜對象的子對象呢?就比如序列里的嵌套序列蜕劝,字典里的嵌套序列等都是復雜對象的子對象檀头。對于子對象,python會把它當作一個公共鏡像存儲起來岖沛,所有對他的復制都被當成一個引用暑始,所以說當其中一個引用將鏡像改變了之后另一個引用使用鏡像的時候鏡像已經(jīng)被改變了。

所以說看這里的origin[2]婴削,也就是 [3, 4] 這個 list廊镜。根據(jù) shallow copy 的定義,在 cop1[2] 指向的是同一個 list [3, 4]唉俗。那么嗤朴,如果這里我們改變了這個 list配椭,就會導致 origin 和 cop1 同時改變。這就是為什么上邊 origin[2][0] = “hey!” 之后雹姊,cop1 也隨之變成了 [1, 2, [‘hey!’, 4]]股缸。

而deepcopy概念圖如下:

deepcopy的時候會將復雜對象的每一層復制一個單獨的個體出來。
這時候的 origin[2] 和 cop2[2] 雖然值都等于 [3, 4]吱雏,但已經(jīng)不是同一個 list了敦姻。即我們尋常意義上的復制。

參考文章:https://blog.csdn.net/qq_32907349/article/details/52190796

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末坎背,一起剝皮案震驚了整個濱河市替劈,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌得滤,老刑警劉巖陨献,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異懂更,居然都是意外死亡眨业,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門沮协,熙熙樓的掌柜王于貴愁眉苦臉地迎上來龄捡,“玉大人,你說我怎么就攤上這事慷暂∑钢常” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵行瑞,是天一觀的道長奸腺。 經(jīng)常有香客問我,道長血久,這世上最難降的妖魔是什么突照? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮氧吐,結果婚禮上讹蘑,老公的妹妹穿的比我還像新娘。我一直安慰自己筑舅,他們只是感情好座慰,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豁翎,像睡著了一般角骤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上心剥,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天邦尊,我揣著相機與錄音,去河邊找鬼优烧。 笑死蝉揍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的畦娄。 我是一名探鬼主播又沾,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼熙卡!你這毒婦竟也來了杖刷?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤驳癌,失蹤者是張志新(化名)和其女友劉穎滑燃,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體颓鲜,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡表窘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甜滨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乐严。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衣摩,靈堂內(nèi)的尸體忽然破棺而出昂验,到底是詐尸還是另有隱情,我是刑警寧澤艾扮,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布既琴,位于F島的核電站,受9級特大地震影響栏渺,放射性物質發(fā)生泄漏呛梆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一磕诊、第九天 我趴在偏房一處隱蔽的房頂上張望填物。 院中可真熱鬧,春花似錦霎终、人聲如沸滞磺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽击困。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間阅茶,已是汗流浹背蛛枚。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留脸哀,地道東北人蹦浦。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像撞蜂,于是被迫代替她去往敵國和親盲镶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容