Python 拓展之詳解深拷貝和淺拷貝

寫在之前

在昨天的文章里 (零基礎(chǔ)學(xué)習(xí) Python 之字典)异雁,寫字典的方法的時候留了一個小尾巴瑰艘,那就是 copy() 方法還沒講是鬼。一是因為 copy 這個方法比較特殊,不單單是它表面的意思紫新;二是以為昨天的文章寫得比較長均蜜,可能你看到那的時候就沒啥耐心去仔細(xì)思考了,但是這個知識點又比較重要芒率,也是面試過程中會被長問起的題囤耳,我之前在面試的時候(干貨滿滿--親身經(jīng)歷的 Python 面試題)就被問起過。所以我把 copy 單獨摘出來今天單講敲董。

正式開始

首先我在這介紹兩個新的小知識紫皇,要在下面用到。一個是函數(shù) id() 腋寨,另一個是運算符 is聪铺。id() 函數(shù)就是返回對象的內(nèi)存地址;is 是比較兩個變量的對象引用是否指向同一個對象萄窜,在這里請不要和 == 混了铃剔,== 是比較兩個變量的值是否相等撒桨。

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> id(a)
38884552L
>>> a is b
False
>>> a == b
True

</pre>

copy 這個詞有兩種叫法,一種是根據(jù)它的發(fā)音音譯過來的键兜,叫拷貝凤类;另一種就是標(biāo)準(zhǔn)的翻譯,叫復(fù)制普气。

其實單從表面意思來說谜疤,copy 就是將某件東西再復(fù)制一份,但是在很多編程語言中现诀,比如 Python夷磕,C++中,它就不是那么的簡單了仔沿。

>>> a = 1
>>> b = a
>>> b
1

看到上面的例子坐桩,從表面上看我們似乎是得到了兩個 1,但是如果你看過我之前寫的文章封锉,你應(yīng)該對一句話有印象绵跷,那就是 “變量無類型”, Python 中變量就是一個標(biāo)簽成福,這里我們有請 id() 閃亮登場碾局,看看它們在內(nèi)存中的位置。

>>> a = 1
>>> b = a
>>> b
1
>>> id(a)
31096808L
>>> id(b)
31096808L

看出來了嗎闷叉,id(a) 和 id(b) 相等擦俐,所以并沒有兩個 1,只是一個 1 而已握侧,只不過是在 1 上貼了兩張標(biāo)簽蚯瞧,名字是 a 和 b 罷了,這種現(xiàn)象普遍存在于 Python 之中品擎,這種賦值的方式實現(xiàn)了 “假裝” 拷貝埋合,真實的情況還是兩個變量和同一個對象之間的引用關(guān)系。

我們再來看 copy() 方法:

>>> a = {'name':'rocky','like':'python'}
>>> b = a.copy()
>>> b
{'name': 'rocky', 'like': 'python'}
>>> id(a)
31036280L
>>> id(b)
38786728L

咦萄传,果然這次得到的 b 和原來的 a 不同甚颂,它是在內(nèi)存中又開辟了一個空間。那么我們這個時候就來推理了秀菱,雖然它們兩個是一樣的振诬,但是它們在兩個不同的內(nèi)存空間里,那么肯定彼此互不干擾衍菱,如果我們?nèi)グ?b 改了赶么,那么 a 肯定不變。

>>> b['name'] = 'leey'
>>> b
{'name': 'leey', 'like': 'python'}
>>> a
{'name': 'rocky', 'like': 'python'}

結(jié)果和我們上面推理的一模一樣脊串,所以理解了對象有類型辫呻,變量無類型清钥,變量是對象的標(biāo)簽,就能正確推斷出 Python 提供的結(jié)果放闺。

我們接下來在看一個例子祟昭,請你在往下看的時候保證上面的你已經(jīng)懂了,不然容易暈車怖侦。

>>> a = {'name':'rocky','like':'python'}
>>> b = a
>>> b
{'name': 'rocky', 'like': 'python'}
>>> b['name'] = 'leey'
>>> b
{'name': 'leey', 'like': 'python'}
>>> a
{'name': 'leey', 'like': 'python'}

上面的例子看出什么來了嗎篡悟?修改了 b 對應(yīng)的字典類型的對象,a 的對象也變了础钠。也就是說恰力, b = a 得到的結(jié)果是兩個變量引用了同一個對象叉谜,但是事情真的這么簡單嗎旗吁?請睜大你的眼睛往下看,重點來了停局。

>>> first = {'name':'rocky','lanaguage':['python','c++','java']}
>>> second = first.copy()
>>> second
{'name': 'rocky', 'lanaguage': ['python', 'c++', 'java']}
>>> id(first)
31036280L
>>> id(second)
38786728L

在這里的話沒有問題很钓,和我們之前說的一樣,second 是從 first 拷貝過來的董栽,它們分別引用的是兩個對象码倦。

>>> second['lanaguage'].remove('java')
>>> second
{'name': 'rocky', 'lanaguage': ['python', 'c++']}
>>> first
{'name': 'rocky', 'lanaguage': ['python', 'c++']}

發(fā)現(xiàn)什么了嗎?按理說上述例子中 second 的 lanaguage 對應(yīng)的是一個列表锭碳,我刪除這個列表里的值袁稽,也只應(yīng)該改變的是 second 啊,為什么連 first 的也會改擒抛,不是應(yīng)該互不干擾嗎推汽?是不是很意外?是我們之前說的不對嗎歧沪?那我們再試試另一個鍵:

>>> second['name'] = 'leey'
>>> second
{'name': 'leey', 'lanaguage': ['python', 'c++']}
>>> first
{'name': 'rocky', 'lanaguage': ['python', 'c++']}

前面說的原理是有效的歹撒,那這到底是為什么啊,來來來诊胞,有請我們的 id() 再次閃亮登場暖夭。

>>> id(first['name'])
38829152L
>>> id(second['name'])
38817544L
>>> id(first['lanaguage'])
38754120L
>>> id(second['lanaguage'])
38754120L

其實這里深層次的原因是和 Python 的存儲數(shù)據(jù)的方式有關(guān),這里不做過多的說明(其實是我也不懂撵孤。迈着。 在這里,我們只需要知道的是邪码,當(dāng) copy() 的時候裕菠,列表這類由字符串,數(shù)字等復(fù)合而成的對象仍然是復(fù)制了引用霞扬,也就是貼標(biāo)簽糕韧,并沒有建立一個新的對象枫振,我們把這種拷貝方式叫做淺拷貝(唉呀媽呀,終于把這個概念引出來了萤彩。粪滤。,言外之意就是并沒有解決深層次的問題雀扶,再言外之意就是還有能夠解決深層次問題的方法杖小。

確實,在 Python 中還有一個深拷貝(deep copy)愚墓,在使用它之前要引入一個 copy 模塊予权,我們來試一下。

>>> import copy
>>> first = {'name':'rocky','lanaguage':['python','c++','java']}
>>> second = copy.deepcopy(first)
>>> second
{'name': 'rocky', 'lanaguage': ['python', 'c++', 'java']}
>>> second['lanaguage'].remove('java')
>>> second
{'name': 'rocky', 'lanaguage': ['python', 'c++']}
>>> first
{'name': 'rocky', 'lanaguage': ['python', 'c++', 'java']}

用了深拷貝以后浪册,果然就不是引用了扫腺。

寫在最后

深拷貝和淺拷貝到這里就講完了,花了一番功夫總算寫的還令自己滿意村象,不知道朋友們看到這里的時候是否是覺得對這一部分豁然開朗笆环,我盡力了。這個拓展也可能是成為一個系列厚者,補(bǔ)充一些我覺得理解起來比較困難或者平時面試求職或者工作中常見的知識點躁劣,希望您多捧場。

最后感謝你能看到這里库菲,希望我寫的東西能夠讓你有到收獲账忘,但是我還是希望我在文章里插入的代碼,你們能自己動手試一下熙宇,都很簡單鳖擒。原創(chuàng)不易,每一個字奇颠,每一個標(biāo)點都是自己手敲的败去,所以希望大家能多給點支持,該關(guān)注關(guān)注烈拒,該點贊點贊圆裕,該轉(zhuǎn)發(fā)轉(zhuǎn)發(fā),有什么問題歡迎在后臺聯(lián)系我荆几,也可以在公眾號 -- Python空間 找到我的微信加我吓妆。

The end。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末吨铸,一起剝皮案震驚了整個濱河市行拢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诞吱,老刑警劉巖舟奠,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件竭缝,死亡現(xiàn)場離奇詭異,居然都是意外死亡沼瘫,警方通過查閱死者的電腦和手機(jī)抬纸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耿戚,“玉大人湿故,你說我怎么就攤上這事∧せ祝” “怎么了坛猪?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長皂股。 經(jīng)常有香客問我墅茉,道長,這世上最難降的妖魔是什么屑墨? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任躁锁,我火速辦了婚禮,結(jié)果婚禮上卵史,老公的妹妹穿的比我還像新娘。我一直安慰自己搜立,他們只是感情好以躯,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著啄踊,像睡著了一般忧设。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上颠通,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天址晕,我揣著相機(jī)與錄音,去河邊找鬼顿锰。 笑死谨垃,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的硼控。 我是一名探鬼主播刘陶,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼牢撼!你這毒婦竟也來了匙隔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤熏版,失蹤者是張志新(化名)和其女友劉穎纷责,沒想到半個月后捍掺,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡再膳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年乡小,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片饵史。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡满钟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胳喷,到底是詐尸還是另有隱情湃番,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布吭露,位于F島的核電站吠撮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏讲竿。R本人自食惡果不足惜泥兰,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望题禀。 院中可真熱鬧鞋诗,春花似錦、人聲如沸迈嘹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽秀仲。三九已至融痛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間神僵,已是汗流浹背雁刷。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留保礼,地道東北人沛励。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像氓英,于是被迫代替她去往敵國和親侯勉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

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

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對...
    cosWriter閱讀 11,113評論 1 32
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,417評論 8 265
  • 包(lib)铝阐、模塊(module) 在Python中址貌,存在包和模塊兩個常見概念。 模塊:編寫Python代碼的py...
    清清子衿木子水心閱讀 3,812評論 0 27
  • 一、Python簡介和環(huán)境搭建以及pip的安裝 4課時實驗課主要內(nèi)容 【Python簡介】: Python 是一個...
    _小老虎_閱讀 5,753評論 0 10
  • 茶已泡好练对,準(zhǔn)備開寫遍蟋。 不是寫文章,是寫材料螟凭。年底的材料太多了虚青。四份個人述職,四份先進(jìn)個人材料螺男,一份先進(jìn)集體材料棒厘,一...
    老鷹飛閱讀 284評論 1 2