Python變量的賦值、淺拷貝和深拷貝詳解
前言
python中為聲明一個(gè)變量有三種方法:賦值、淺拷貝(shadow copy)、深拷貝(deep copy),相信每個(gè)pythoner或多或少都知道他們之間的區(qū)別,但在某些點(diǎn)上,還是會(huì)踩坑,這篇文章記錄下所有關(guān)于這三者區(qū)別的疑問(wèn)。
對(duì)比
在理解以上幾個(gè)概念區(qū)別之前需要明確以下問(wèn)題:
- 賦值傳遞的是原始對(duì)象的地址
- 函數(shù)傳遞形參也是傳遞地址,該地址指向原始對(duì)象,多進(jìn)程的task函數(shù)除外,多進(jìn)程中task函數(shù)的形參和原始對(duì)象是完全不同的兩個(gè)對(duì)象,類似深拷貝(進(jìn)程間內(nèi)存獨(dú)立)
- 淺拷貝,除了顯式地調(diào)用copy庫(kù),還可以使用如切片、list()、dict()等函數(shù)達(dá)到淺拷貝的效果(下面會(huì)給例子)。
- 當(dāng)我們討論python中的拷貝時(shí),默認(rèn)針對(duì)的是可變對(duì)象,因?yàn)閷?duì)于不可變對(duì)象來(lái)講,拷貝是沒(méi)有意義的,python解釋器在啟動(dòng)時(shí)就將不可變對(duì)象放在內(nèi)存池中了,它在內(nèi)存的位置在解釋器終止之前不會(huì)變。假設(shè)我們通過(guò)賦值、淺拷貝、深拷貝得到了一個(gè)新的對(duì)象,那么與原始對(duì)象相比,有以下結(jié)論:
| / | 賦值 | 淺拷貝 | 深拷貝 |
| id是否變化 | × | ? | ? |
| 修改對(duì)象本身是否互相影響 | ? | × | × |
| 修改嵌套對(duì)象是否互相影響 | ? | ? | × |
具體例子
a = ['a', 1, [1,2]]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
print(f'c is: {c} , id is: {id(c)}')
print(f'd is: gr7kqhn , id is: {id(d)}')
輸出:
a is: ['a', 1, [1, 2]] , id is: 140211144620672
b is: ['a', 1, [1, 2]] , id is: 140211144620672
c is: ['a', 1, [1, 2]] , id is: 140211144622016
d is: ['a', 1, [1, 2]] , id is: 140211144620992
可以看出,賦值得到的新對(duì)象id與原始對(duì)象id相同,拷貝得到的新對(duì)象id與原始對(duì)象不同。
# 對(duì)對(duì)象本身進(jìn)行修改,即“最外層”
a.append(2)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
print(f'c is: {c} , id is: {id(c)}')
print(f'd is: evrsfqs , id is: {id(d)}')
輸出:
a is: ['a', 1, [1, 2], 2] , id is: 140211144620672
b is: ['a', 1, [1, 2], 2] , id is: 140211144620672
c is: ['a', 1, [1, 2]] , id is: 140211144622016
d is: ['a', 1, [1, 2]] , id is: 140211144620992
可以看出,修改對(duì)象本身對(duì)拷貝對(duì)象沒(méi)有影響。 再修改嵌套對(duì)象:
# 修改嵌套對(duì)象
a[2].append(3)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
print(f'c is: {c} , id is: {id(c)}')
print(f'd is: hqgxou2 , id is: {id(d)}')
輸出:
a is: ['a', 1, [1, 2, 3], 2] , id is: 140211144620672
b is: ['a', 1, [1, 2, 3], 2] , id is: 140211144620672
c is: ['a', 1, [1, 2, 3]] , id is: 140211144622016
d is: ['a', 1, [1, 2]] , id is: 140211144620992
可以看出,修改嵌套對(duì)象,對(duì)淺拷貝對(duì)象有影響,對(duì)深拷貝對(duì)象無(wú)影響。 再看下不可變對(duì)象1的id:
print(f'1 id in a is {id(a[1])}')
print(f'1 id in b is {id(b[1])}')
print(f'1 id in c is {id(c[1])}')
print(f'1 id in d is {id(d[1])}')
輸出:
1 id in a is 140279957373168
1 id in b is 140279957373168
1 id in c is 140279957373168
1 id in d is 140279957373168
可以看出,所有對(duì)象的不可變對(duì)象指向了同一個(gè)位置,事實(shí)上,即便在同一個(gè)對(duì)象中相同的不可變對(duì)象也是指向同一個(gè)位置:
print(f'a is {a}')
print(f'{id(a[1])}, {id(a[2][0])}')
輸出:
a is ['a', 1, [1, 2, 3], 2]
140168057503984, 140168057503984
除了顯示地使用copy.copy()獲得一個(gè)淺拷貝對(duì)象,list()、dict()等對(duì)象工廠也可以獲得一個(gè)淺拷貝對(duì)象:
a = ['a', 1, [1,2]]
b = list(a)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
a[2].append(3)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
輸出:
a is: ['a', 1, [1, 2]] , id is: 139717765197952
b is: ['a', 1, [1, 2]] , id is: 139718287865280
a is: ['a', 1, [1, 2, 3]] , id is: 139717765197952
b is: ['a', 1, [1, 2, 3]] , id is: 139718287865280
可以看出,a與b的id不同,但修改嵌套對(duì)象會(huì)互相影響,所以b是a的淺拷貝對(duì)象。
切片也類似,是一個(gè)淺拷貝對(duì)象:
a = ['a', 1, [1,2]]
b = a[-1:]
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
a[2].append(3)
print(f'a is: {a} , id is: {id(a)}')
print(f'b is: , id is: {id(b)}')
輸出:
a is: ['a', 1, [1, 2]] , id is: 140294636448256
b is: [[1, 2]] , id is: 140294636449408
a is: ['a', 1, [1, 2, 3]] , id is: 140294636448256
b is: [[1, 2, 3]] , id is: 140294636449408
到此這篇關(guān)于Python變量的賦值、淺拷貝和深拷貝詳解的文章就介紹到這了,更多相關(guān)Python賦值、淺拷貝和深拷貝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pymysql之cur.fetchall() 和cur.fetchone()用法詳解
這篇文章主要介紹了pymysql之cur.fetchall() 和cur.fetchone()用法詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
Python中的is和==比較兩個(gè)對(duì)象的兩種方法
這篇文章主要介紹了Python中的is和==比較兩個(gè)對(duì)象的兩種方法的相關(guān)資料,希望通過(guò)本文能幫助到大家,需要的朋友可以參考下2017-09-09
Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)從字典中提取子集的方法示例
這篇文章主要介紹了Python cookbook(數(shù)據(jù)結(jié)構(gòu)與算法)從字典中提取子集的方法,涉及Python字典推導(dǎo)式的相關(guān)使用技巧,需要的朋友可以參考下2018-03-03
詳解python OpenCV學(xué)習(xí)筆記之直方圖均衡化
本篇文章主要介紹了詳解python OpenCV學(xué)習(xí)筆記之直方圖均衡化,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
python des,aes,rsa加解密的實(shí)現(xiàn)
這篇文章主要介紹了python des,aes,rsa加解密的實(shí)現(xiàn),幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01
Python如何實(shí)現(xiàn)自動(dòng)生成指定文件名并自定義后綴名
這篇文章主要為大家詳細(xì)介紹了Python如何實(shí)現(xiàn)名稱為000- 999-文件的自動(dòng)生成,并且后綴名可以自定義,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02

