賦值、深拷貝训貌、淺拷貝

# -*- coding: utf-8 -*-
# @Time    : 2019/11/27 20:08
# @Author  : John
# @Email   : 2398344557@qq.com
# @File    : 賦值+拷貝.py
# @Software: PyCharm
賦值/函數(shù)參數(shù)傳遞

傳遞的永遠都是對象引用(內(nèi)存地址)制肮,而不是對象的內(nèi)容
因為指向的都是同一塊內(nèi)存
所以冒窍,內(nèi)外層共享,你變我也變

對象分為兩種:可變對象(mutable)和不可變對象(immutable)
類型不同豺鼻,決定了可以對它進行的操作不同综液。

對象的拷貝是指在內(nèi)存中創(chuàng)建新的對象,產(chǎn)生新的內(nèi)存地址儒飒。
當頂層對象和它的子元素對象全為immutable不可變對象時谬莹,不存在被拷貝,因為沒有產(chǎn)生新對象桩了。

可變對象(mutable)
例如:list附帽、dict、

不可變對象(immutable)
例如:number圣猎、string士葫、tuple、frozenset

賦值/函數(shù)參數(shù)傳遞:傳遞的永遠是對象引用(即內(nèi)存地址)送悔,而不是對象內(nèi)容慢显。
淺拷貝(Shallow Copy):拷貝頂層對象,但不會拷貝內(nèi)部子元素對象欠啤。
深拷貝(Deep Copy):遞歸拷貝頂層對象荚藻,以及它內(nèi)部的子元素對象。

a = 1
b = a
print(id(a))   # a指向了1所應(yīng)有的內(nèi)存
print(id(b))   # b也指向了1所應(yīng)有的內(nèi)存
# a == b
# id(a) == id(b)
# 1808255104
# 1808255104

b += 1
print(a)   # a指向了1所應(yīng)有的內(nèi)存
print(b)    # b另尋新歡洁段,指向了2所對應(yīng)的內(nèi)存
print(id(a))
print(id(b))
# a != b
# id(a) != id(b)
# 1
# 2
# 1808255104
# 1808255120

a += 1
print(a)   # a指向了2所應(yīng)有的內(nèi)存
print(b)    # b指向了2所對應(yīng)的內(nèi)存
print(id(a))
print(id(b))
# a == b
# id(a) == id(b)
# 2
# 2
# 1808255120
# 1808255120

# 結(jié)論:
# 要是b改變了应狱,那么a不受影響
# 要是a改變了,b會跟著改變
# Python會緩存使用頻率較多的整數(shù)-5到256祠丝、ISO/IEC 8859-1單字符疾呻、包括大小寫英文字母的字符串,以對其復用写半,不會創(chuàng)建新對象
a = 1000000000
b = 1000000000
print(id(a))
print(id(b))
a = -10
b = -10
print(id(a))
print(id(b))
a = 'x*y'
b = 'x*y'
print(id(a))
print(id(b))
a = 'Hello World'
b = 'Hello World'
print(id(a))
print(id(b))

------------------------------------------------------------------------

copy模塊

  1. 對象拷貝是指內(nèi)存中創(chuàng)建新的對象岸蜗,產(chǎn)生新的內(nèi)存地址
  2. 淺拷貝只拷貝最外層對象,深拷貝還會遞歸拷貝內(nèi)層對象
  3. 無論是淺拷貝還是深拷貝叠蝇,只拷貝mutable可變對象成為一個新對象璃岳;而immutable不可變對象還是原來的那個
  4. 當頂層對象和它的子元素對象全都是immutable不可變對象時,因為沒有產(chǎn)生新對象悔捶,所以不存在被拷貝
淺拷貝(Shallow Copy):拷貝頂層對象铃慷,但不會拷貝內(nèi)部的子元素對象
    1. 頂層是mutable,子元素全是immutable
# 當頂層對象時mutable可變對象蜕该,但是它的子元素對象全都是immutable不可變對象時犁柜,例如[1, 'world', 2]
a = [1, 'world', 2]
from copy import copy
b = copy(a)
# 最外層
print(a)
print(b)
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])

a[0] = 3    # 整數(shù)為不可改變對象
a[1] = 'back'    # 字符串為可改變對象
print(a)
print(b)
print(id(a))
print([id(item) for item in a])
print(id(b))
print([id(item) for item in b])
# [3, 'back', 2]
# [1, 'world', 2]
# 205803315784
# [140715228312464, 205808370440, 140715228312432]
# 205803315848
# [140715228312400, 205803779440, 140715228312432]

# 結(jié)論:
# 淺拷貝:
# 最外層內(nèi)存地址改變
# 第一層內(nèi),改變immutable對象時堂淡,元素內(nèi)存地址改變馋缅;改變mutable對象時坛怪,元素內(nèi)存地址不變
    1. 頂層是mutable,子元素部分是immutable
# 當頂層對象時mutable可變對象股囊,但子元素也存在mutable可變對象時,如[1, 2, ['hello', 'word']]
a = [1, 2, ['hello', 'world']]
from copy import copy
b = copy(a)
# 最外層
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])
# 第二層
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])

# 最外層
# 147762995848
# 147890515400
# 第一層
# [140714968986448, 140714968986480, 147762995784]
# [140714968986448, 140714968986480, 147762995784]
# 第二層
# [147763459440, 147763459496]
# [147763459440, 147763459496]

a[2][1] = 'china'
print(a)
print(b)
# 第二層()
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])
# [1, 2, ['hello', 'china']]
# [1, 2, ['hello', 'china']]
# [879935386992, 879935387216]
# [879935386992, 879935387216]
# -----------
b[2][1] = 'china'
print(a)
print(b)
# 第二層()
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])
# [1, 2, ['hello', 'china']]
# [1, 2, ['hello', 'china']]
# [853162423664, 853162423888]
# [853162423664, 853162423888]
    1. 頂層是immutable更啄,子元素全是immutable
# 當頂層對象是immutable不可變對象稚疹,同時子元素對象也全是immutable不可變對象時,例如(1, 2, 3)
a = (1, 2, 3)
from copy import copy
b = copy(a)
# 最外層
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])
# 926788983616
# 926788983616
# [140715035439952, 140715035439984, 140715035440016]
# [140715035439952, 140715035439984, 140715035440016]
# 結(jié)論:變量a與變量b指向的是同一個元組對象祭务,沒有拷貝
    1. 頂層是immutable内狗,子元素部分mutable
# 當頂層對象是immutable不可變對象時,但子元素存在mutable可變對象時义锥,如(1, 2, ['hello','world'])
a = (1, 2, ['hello', 'world'])
from copy import copy
b = copy(a)
# 最外層
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])
# 第二層
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])

# 956919749512
# 956919749512
# [140715035439952, 140715035439984, 956889129544]
# [140715035439952, 140715035439984, 956889129544]
# [956916987248, 956916987304]
# [956916987248, 956916987304]

# 修改第二層
a[2][1] = 'china'
print(a)
print(b)
# b[2][1] = 'china'
# print(a)
# print(b)
# # (1, 2, ['hello', 'china'])
# # (1, 2, ['hello', 'china'])
# 結(jié)論:變量a和變量b指向同樣的元租對象柳沙,并且a[2]與b[2]指向同一個列表,所以修改a[2][1]會影響b[2][1]
深拷貝(Deep Copy):遞歸拷貝頂層對象拌倍,以及它內(nèi)部的子元素對象
    1. 頂層是mutable赂鲤,子元素全是immutable
# 當頂層對象是mutable可變對象,但是它的子元素對象全都是immutable不可變對象時柱恤,如[1, 'world', 2]
a = [1, 'world', 2]
from copy import deepcopy
b = deepcopy(a)
print(a)
print(b)
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])
# 第二層
print([id(a[1])])
print([id(b[1])])

# [1, 'world', 2]
# [1, 'world', 2]
# 249343140424
# 249343140488
# [140715035439952, 249343604080, 140715035439984]
# [140715035439952, 249343604080, 140715035439984]
# 249343604080
# 249343604080

# a[0] = 3
# a[1] = 'xuebi'
# print(a)
# print(b)
# print([id(item) for item in a])
# print([id(item) for item in b])

# b[0] = 3
# b[1] = 'xuebi'
# print(a)
# print(b)
# print([id(item) for item in a])
# print([id(item) for item in b])
# 結(jié)論:變量a與變量b指向不同的列表對象数初,修改a[0]只是將列表a的第一個元素重新指向新對象,不會影響b[0]
    1. 頂層是immutable梗顺,子元素部分mutable
# 當頂層對象是immutable不可變對象時泡孩,但子元素存在mutable可變對象時,如(1, 2, ['hello','world'])

a = (1, 2, ['hello', 'world'])
import copy
b = copy.deepcopy(a)
# 最外層
print(id(a))
print(id(b))
# 第一層
print([id(item) for item in a])
print([id(item) for item in b])
# 第二層
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])

# 最外層
# 6333064
# 74784040
# 第一層
# [1685506176, 1685506192, 1656272]
# [1685506176, 1685506192, 74867736]
# 第二層
# [2289152, 2289184]
# [2289152, 2289184]

a[2][1] = 'china'
print(a)
print(b)
print([id(item) for item in a[2]])
print([id(item) for item in b[2]])

# (1, 2, ['hello', 'china'])
# (1, 2, ['hello', 'world'])
# [2289152, 2289280]
# [2289152, 2289184]

# 結(jié)論:變量a與變量b指向的是不同的元組對象寺谤,同時a[2]與b[2]指向不同的列表對象仑鸥,所以修改a[2][1]不會影響b[2][1]

【例子】

class dog:
    def __init__(self, age):
        self.age = age
        self.foods = ['gutou', 'gouliang', 'jichibang']
    def __repr__(self):
        return f'dog is {self.age}, dog like eat {self.foods}.'
dog1 = dog(10)
print(dog1)
# dog is 10, dog like eat ['gutou', 'gouliang', 'jichibang'].
dog2 = copy.copy(dog1)
dog1.age = 50
dog1.foods[0] = 'maoliang'
print(dog1)
print(dog2)
# dog is 50, dog like eat ['maoliang', 'gouliang', 'jichibang'].
# dog is 10, dog like eat ['maoliang', 'gouliang', 'jichibang'].
# 分析:
# 年齡在第一層,不變变屁;foods列表在第二層眼俊,會變

【例子】

class home:
    def __init__(self, addr):
        self.addr = addr
    def __repr__(self):
        return self.addr
class dog:
    def __init__(self, age, addr, name):
        self.name = name
        self.age = age
        self.home = home(addr)
    def __repr__(self):
        return f'dog is {self.age}, my home is {self.home}, my name is {self.name}'
dog1 = dog(20, '美國', 'ruhua')
print(dog1)
# dog is 20, my home is 美國, my name is ruhua
dog2 = copy.copy(dog1)
dog1.age = 30
dog1.name = 'panghu'
dog1.home.addr = 'afuhan'
print(dog1)
print(dog2)
# dog is 30, my home is afuhan, my name is panghu
# dog is 20, my home is afuhan, my name is ruhua
# 分析:
# age和name在第一層,不變敞贡;home在第二層泵琳,會變
其它拷貝方法
  • 列表的復制
a = [1, 2, 3]
b = a
# 變化前:a == b
print(b)
print(id(a))
print(id(b))
a[0] = 'xuebi'
# 變化后:a == b
print(a)
print(b)
print(id(a))
print(id(b))

# [1, 2, 3]
# 4933072
# 4933072
# ['xuebi', 2, 3]
# ['xuebi', 2, 3]
# 4933072
# 4933072

# 但是,列表的復制也會有淺拷貝的效果誊役,如下:
a = [1, 2, ['hello','world']]
# 1. 列表的copy()函數(shù)
b = a.copy()
# 2. list()轉(zhuǎn)換函數(shù)
c = list(a)
# 3. 列表分片[:]
d = a[:]

print(id(a), id(b), id(c), id(d))
# 4672088 74736824 13781432 13648800

a[0] = 100
a[2][1] = 'wangy'
print(a)
print(b)
print(c)
print(d)
print(id(a), id(b), id(c), id(d))
# [100, 2, ['hello', 'wangy']]
# [1, 2, ['hello', 'wangy']]
# [1, 2, ['hello', 'wangy']]
# [1, 2, ['hello', 'wangy']]
# 4672088 74736824 13781432 13648800

# 結(jié)論:b/c/d都是a的復制获列,它們都指向了不同的列表對象,但是沒有拷貝子元素蛔垢,a[2]和b[2]/c[2]/d[2]指向同一個列表击孩,相當于淺拷貝的效果

  • 元組的復制
a = (1, 2, ['hello','world'])
b = a[:]
print(id(a), id(b))
print(a)
print(b)
# 35496504 35496504
# (1, 2, ['hello', 'world'])
# (1, 2, ['hello', 'world'])

a[2][1] = 'wangy'
print(a)
print(b)
print(id(a), id(b))

# (1, 2, ['hello', 'world'])
# (1, 2, ['hello', 'world'])
# (1, 2, ['hello', 'wangy'])
# (1, 2, ['hello', 'wangy'])
# 35496504 35496504

# 結(jié)論:使用分片[:]操作,a和b其實是指向同一個元組鹏漆,而且沒有拷貝子元素巩梢,a[2]和b[2]也指向同一個列表创泄,相當于淺拷貝的效果

  • 字典的復制
# 字典的復制
# 同列表類似,可以使用字典的copy()函數(shù)或者轉(zhuǎn)換函數(shù)dict()
a = {'name': 'wangy', 'age': 18, 'jobs': ['devops', 'dba']}
b = a.copy()
c = dict(a)
print(id(a), id(b), id(c))
# 14499392 14012304 5470848

a['age'] = 20
a['jobs'].append('python')
print(a)
print(b)
print(c)
print(id(a), id(b), id(c))
# {'name': 'wangy', 'age': 20, 'jobs': ['devops', 'dba', 'python']}
# {'name': 'wangy', 'age': 18, 'jobs': ['devops', 'dba', 'python']}
# {'name': 'wangy', 'age': 18, 'jobs': ['devops', 'dba', 'python']}
# 14499392 14012304 5470848

# 結(jié)論:變量a與變量b/c指向不同的字典括蝠,但是沒有拷貝子元素鞠抑,a['jobs']和b['jobs']/c['jobs']指定同一個列表,相當于淺拷貝的效果

  • 集合的復制
# 同列表類似忌警,可以使用集合的copy()函數(shù)或者轉(zhuǎn)換函數(shù)set()
a = {1, 2, 3}
b = a.copy()
c = set(a)
print(id(a), id(b), id(c))
# 2731824 35400440 35400560

a.add('wangy')
print(a)
print(b)
print(c)
print(id(a), id(b), id(c))
# {1, 2, 3, 'wangy'}
# {1, 2, 3}
# {1, 2, 3}
# 2731824 35400440 35400560

# 結(jié)論:變量a與變量b/c指向不同的集合搁拙,而集合的元素必須是hashable,所以修改集合a不會影響到b/c

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末法绵,一起剝皮案震驚了整個濱河市箕速,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌朋譬,老刑警劉巖盐茎,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異徙赢,居然都是意外死亡字柠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門犀忱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來募谎,“玉大人,你說我怎么就攤上這事阴汇∈” “怎么了?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵搀庶,是天一觀的道長拐纱。 經(jīng)常有香客問我,道長哥倔,這世上最難降的妖魔是什么秸架? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮咆蒿,結(jié)果婚禮上东抹,老公的妹妹穿的比我還像新娘。我一直安慰自己沃测,他們只是感情好缭黔,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蒂破,像睡著了一般馏谨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上附迷,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天惧互,我揣著相機與錄音哎媚,去河邊找鬼。 笑死喊儡,一個胖子當著我的面吹牛拨与,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艾猜,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼截珍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箩朴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤秋度,失蹤者是張志新(化名)和其女友劉穎炸庞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荚斯,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡埠居,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了事期。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滥壕。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖兽泣,靈堂內(nèi)的尸體忽然破棺而出绎橘,到底是詐尸還是另有隱情,我是刑警寧澤唠倦,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布称鳞,位于F島的核電站,受9級特大地震影響稠鼻,放射性物質(zhì)發(fā)生泄漏冈止。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一候齿、第九天 我趴在偏房一處隱蔽的房頂上張望熙暴。 院中可真熱鬧,春花似錦慌盯、人聲如沸周霉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诗眨。三九已至,卻和暖如春孕讳,著一層夾襖步出監(jiān)牢的瞬間匠楚,已是汗流浹背巍膘。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芋簿,地道東北人峡懈。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像与斤,于是被迫代替她去往敵國和親肪康。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

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