[開篇四:Python零散知識拾荒之深淺拷貝]2018-11-06

Python當中對于拷貝乙嘀,分為兩種類型。一種是數(shù)字和字符串婴噩,另一種就是列表几莽、元組章蚣、字典等其他類型了。

一峭沦、數(shù)字和字符串的拷貝

1吼鱼、賦值

舉個栗子:

a1 = 123123
a2 = 123123
# a2 = a1  # 賦值
print(id(a1))  # 通過id()函數(shù)來打印變量在內(nèi)存當中的地址
print(id(a2))

輸出結(jié)果是:

1959780298352
1959780298352 

??在以上代碼塊當中庆尘,a2與a1所賦的值是一樣的,都是數(shù)字123123笑跛。因為python有一個重用機制飞蹂,對于同一個數(shù)字,python并不會開辟一塊新的內(nèi)存空間惊窖,而是維護同一塊內(nèi)存地址界酒,只是將該數(shù)字對應的內(nèi)存地址的引用賦值給變量a1和a2。所以根據(jù)輸出結(jié)果凭疮,a1和a2其實對應的是同一塊內(nèi)存地址执解,只是兩個不同的引用罷了。同樣的桶唐,對于a2 = a1尤泽,其實效果等同于“a1 = 123123; a2 = 123123”熊咽,它也就是將a1指向123123的引用賦值給a2横殴。字符串跟數(shù)字的原理雷同衫仑,如果把123123改成“abcabc”也是一樣的。*

結(jié)論:對于通過用 = 號賦值瞄崇,數(shù)字和字符串 在內(nèi)存當中用的都是同一塊地址苏研。

2、淺拷貝

import copy  # 使用淺拷貝需要導入copy模塊
 
a1 = 123123
a3 = copy.copy(a1)  # 使用copy模塊里的copy()函數(shù)就是淺拷貝了
print(id(a1))
print(id(a3))

輸出結(jié)果是:

35233168
35233168

??通過使用copy模塊里的copy()函數(shù)來進行淺拷貝纹蝴,把a1拷貝一份賦值給a3,查看輸出結(jié)果發(fā)現(xiàn)兼犯,a1和a3的內(nèi)存地址還是一樣切黔。

結(jié)論:對于淺拷貝,數(shù)字和字符串在內(nèi)存當中用的也是同一塊地址诗芜。

3孩哑、深拷貝

舉個栗子:

import copy

a1 = 123123
a4 = copy.deepcopy(a1)  # 深拷貝是用copy模塊里的deepcopy()函數(shù)
print(id(a1))
print(id(a4))

輸出結(jié)果為:

31432080
31432080

查看結(jié)果發(fā)現(xiàn)横蜒,對于深拷貝,數(shù)字和字符串在內(nèi)存當中用的也是同一塊地址。

所以綜上所述孟岛,對于數(shù)字和字符串的賦值、淺拷貝次询、深拷貝在內(nèi)存當中用的都是同一塊地址。原理如下圖:

image

二、字典蔽介、列表、元組等其他類型的拷貝

1薇组、賦值

舉個栗子:

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
n2 = n1  # 賦值
print(id(n1))
print(id(n2))

輸出結(jié)果:

2235551677536
2235551677536

??我們的栗子當中用了一個字典n1专钉,字典里面嵌套了一個列表跃须,當我們把n1賦值給n2時,內(nèi)存地址并沒有發(fā)生變化第练,因為其實它也是只是把n1的引用拿過來賦值給n2而已。(我們用了一個字典來舉例婴梧,其他類型也是一樣的)

原理如下圖:

image.png

結(jié)論:對于賦值,字典番电、列表、元組等其他類型用的內(nèi)存地址不會變化洼冻。

2撞牢、淺拷貝

舉個栗子:

import copy

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
n3 = copy.copy(n1)  # 淺拷貝
print("第一層字典的內(nèi)存地址:")
print(id(n1))
print(id(n3))
print("第二層嵌套的列表的內(nèi)存地址:")
print(id(n1["k3"]))
print(id(n3["k3"]))

輸出結(jié)果:

第一層字典的內(nèi)存地址:
6516024
6516096
第二層嵌套的列表的內(nèi)存地址:
36995720
36995720

??通過以上結(jié)果可以看出,進行淺拷貝時,我們的字典第一層n1和n3指向的內(nèi)存地址已經(jīng)改變了蟹但,但是對于第二層里的列表并沒有拷貝麦向,它的內(nèi)存地址還是一樣的诵竭。原理如下圖:

image

結(jié)論:所以對于淺拷貝,字典兼搏、列表卵慰、元組等類型,它們只拷貝第一層地址

3佛呻、深拷貝

舉個栗子:

import copy

n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 678]}
n4 = copy.deepcopy(n1)  # 深拷貝
print("第一層字典的內(nèi)存地址:")
print(id(n1))
print(id(n4))
print("第二層嵌套的列表的內(nèi)存地址:")
print(id(n1["k3"]))
print(id(n4["k3"]))

輸出結(jié)果:

第一層字典的內(nèi)存地址:
31157560
35463600
第二層嵌套的列表的內(nèi)存地址:
35947144
35947336

??通過以上結(jié)果發(fā)現(xiàn)裳朋,進行深拷貝時吓著,字典里面的第一層和里面嵌套的地址都已經(jīng)變了鲤嫡。對于深拷貝,它會拷貝多層夜矗,將第二層的列表也拷貝一份泛范,如果還有第三層嵌套让虐,那么第三層的也會拷貝紊撕,但是對于里面的最小元素,比如數(shù)字和字符串赡突,這里就是“wu”对扶,123,“alex”惭缰,678之類的浪南,按照python的機制,它們會共同指向同一個位置漱受,它的內(nèi)存地址是不會變的络凿。原理如下圖:

image

結(jié)論:對于深拷貝,字典昂羡、列表絮记、元組等類型,它里面嵌套多少層虐先,就會拷貝多少層出來怨愤,但是最底層的數(shù)字和字符串地址不變。

舉個實際應用場景的栗子蛹批。

我們在維護服務器信息的時候撰洗,經(jīng)常會要更新服務器信息篮愉,這時我們重新一個一個添加是比較麻煩的,我們可以把原數(shù)據(jù)類型拷貝一份差导,在它的基礎上做修改试躏。

栗子一、使用淺拷貝

import copy


dic = {
    "cpu": [80, ],
    "mem": [80, ],
    "disk": [80, ]
}
# 定義了一個字典柿汛,存儲服務器信息冗酿。
print('before', dic)
new_dic = copy.copy(dic)
new_dic['cpu'][0] = 50  # 更新cpu為50
print(dic)
print(new_dic)

輸出結(jié)果為:

before {'cpu': [80], 'mem': [80], 'disk': [80]}
{'cpu': [50], 'mem': [80], 'disk': [80]}
{'cpu': [50], 'mem': [80], 'disk': [80]}

這時我們會發(fā)現(xiàn),使用淺拷貝時络断,我們修改新的字典的值之后裁替,原來的字典里面的cpu值也被修改了,這并不是我們希望看到的貌笨。

栗子二弱判、使用深拷貝

import copy


dic = {
    "cpu": [80, ],
    "mem": [80, ],
    "disk": [80, ]
}
print('before', dic)
new_dic = copy.deepcopy(dic)
new_dic['cpu'][0] = 50
print(dic)
print(new_dic)

輸出結(jié)果:

before {'cpu': [80], 'mem': [80], 'disk': [80]}
{'cpu': [80], 'mem': [80], 'disk': [80]}
{'cpu': [50], 'mem': [80], 'disk': [80]}

??使用深拷貝的時候,發(fā)現(xiàn)只有新的字典的cpu值被修改了锥惋,原來的字典里面的cpu值沒有變昌腰。大功告成!

總結(jié)

  • 賦值(=):數(shù)據(jù)完全共享(賦值是在內(nèi)存中指向同一個對象膀跌,如果是可變(mutable)類型遭商,比如列表,修改其中一個捅伤,另一個必定改變劫流;如果是不可變類型(immutable),比如字符串,修改了其中一個丛忆,另一個并不會變)
  • 淺拷貝:數(shù)據(jù)半共享(復制其數(shù)據(jù)獨立內(nèi)存存放祠汇,但是只拷貝成功第一層)
  • 深拷貝:數(shù)據(jù)完全不共享(復制其數(shù)據(jù)完完全全放獨立的一個內(nèi)存,完全拷貝熄诡,數(shù)據(jù)不共享)可很;深拷貝就是完完全全復制了一份,且數(shù)據(jù)不會互相影響凰浮,因為內(nèi)存不共享我抠。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市袜茧,隨后出現(xiàn)的幾起案子菜拓,更是在濱河造成了極大的恐慌,老刑警劉巖惫周,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件尘惧,死亡現(xiàn)場離奇詭異,居然都是意外死亡递递,警方通過查閱死者的電腦和手機喷橙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門啥么,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贰逾,你說我怎么就攤上這事悬荣。” “怎么了疙剑?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵氯迂,是天一觀的道長。 經(jīng)常有香客問我言缤,道長嚼蚀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任管挟,我火速辦了婚禮轿曙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘僻孝。我一直安慰自己导帝,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布穿铆。 她就那樣靜靜地躺著您单,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荞雏。 梳的紋絲不亂的頭發(fā)上虐秦,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音讯檐,去河邊找鬼羡疗。 笑死染服,一個胖子當著我的面吹牛别洪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柳刮,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼挖垛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秉颗?” 一聲冷哼從身側(cè)響起痢毒,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蚕甥,沒想到半個月后哪替,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡菇怀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年凭舶,在試婚紗的時候發(fā)現(xiàn)自己被綠了晌块。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡帅霜,死狀恐怖匆背,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情身冀,我是刑警寧澤钝尸,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站搂根,受9級特大地震影響珍促,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜剩愧,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一踢星、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧隙咸,春花似錦沐悦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至充包,卻和暖如春副签,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背基矮。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工淆储, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人家浇。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓本砰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钢悲。 傳聞我的和親對象是個殘疾皇子点额,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

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

  • 可變(mutable)和不可變(immutable)參數(shù) 不可變對象在進行重新賦值的時候,實際上是將原始值丟棄莺琳,將...
    樓程智閱讀 1,213評論 1 1
  • 1.ios高性能編程 (1).內(nèi)層 最小的內(nèi)層平均值和峰值(2).耗電量 高效的算法和數(shù)據(jù)結(jié)構(gòu)(3).初始化時...
    歐辰_OSR閱讀 29,343評論 8 265
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,093評論 1 32
  • php -m windows 下查看php已開啟的拓展 GMP是The GNU MP Bignum Libra...
    jianghu000閱讀 2,337評論 0 0
  • 俗話說救人一命还棱,勝造七級浮屠 一、 月圓之夜惭等,大部分的人都已早早下班珍手,和自己的親朋好友聚在一起,聊天喝酒賞圓月。然...
    2B繪畫鉛筆閱讀 299評論 1 0