最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

淺顯直白的Python深拷貝與淺拷貝區(qū)別說明

2023-02-23 07:08 作者:程序員-王堅  | 我要投稿

一、可變數(shù)據(jù)類型與不可變數(shù)據(jù)類型

  在開始說深拷貝與淺拷貝前,我們先來弄清楚,可變對象與不可變對象

  總的來說,Python數(shù)據(jù)類型可分為可變數(shù)據(jù)類型與不可變數(shù)據(jù)類型

  可變數(shù)據(jù)類型:在不改變對象所指向的地址的前提下,地址中的值是可以改變的,例如列表[1, 2, 3],我們可以改為[2,3]并不需要變更它指向的地址。列表、字典、集合都是可變數(shù)據(jù)類型

  不可變數(shù)據(jù)類型:在不改變對象所指向的地址的前提下,地址中的值是不可變的,所以如果修改了對象的值,就相當(dāng)于在另一個新的地址,存儲了新的值。Python中元組、字符串、數(shù)值、布爾值都是不可變數(shù)據(jù)類型。

?

二、Python深拷貝與淺拷貝的區(qū)別

  在弄清楚了可變對象和不可變對象之后,我們進(jìn)入正題,看下Python的深拷貝與淺拷貝的區(qū)別

  1. 淺拷貝:

   僅拷貝父對象,可理解為僅拷貝對象第一層。淺拷貝之后,新舊對象本身指向的地址不同了,但子對象指向的地址仍然相同,我們可以用copy.copy()和可變數(shù)據(jù)類型的切片來進(jìn)行淺拷貝

m = [1, 0, [2, 3, 4, [5, 6]]]
n = m.copy()
p = m[:]
print(f'對象m的地址是{id(m)},對象n的地址是{id(n)},對象p的地址是{id(p)}')
print(f'm[0]的地址是{id(m[0])},n[0]的地址是{id(n[0])},p[0]的地址是{id(p[0])}')
print(f'm[2]的地址是{id(m[2])},n[2]的地址是{id(n[2])},p[2]的地址是{id(p[2])}')輸出:

對象m的地址是1322908811144,對象n的地址是1322908811080,對象p的地址是1322908763400
m[0]的地址是140727539432512,n[0]的地址是140727539432512,p[0]的地址是140727539432512
m[2]的地址是1322908811208,n[2]的地址是1322908811208,p[2]的地址是1322908811208

打印結(jié)果可以看到,淺拷貝之后,新對象n, p的地址與m不同,但n, p的子對象地址與m中子對象地址是相同的

  ? 此時,我們對新對象的子對象進(jìn)行修改,我們來修改一下n[0]看一下結(jié)果

n[0] =99print(f' m[0]={m[0]}\n n[0]={n[0]}\n p[0]={p[0]}')print(f' m[0]的地址:{id(m[0])}\n n[0]的地址:{id(n[0])}\n p[0]的地址:{id(p[0])}') 輸出: m[0]=1 n[0]=99 p[0]=1 m[0]的地址:140727543364672 n[0]的地址:140727543367808 p[0]的地址:140727543364672

  ? 可以看到,n[0]的地址和值都變了, m[0]和p[0]并沒有變,是為什么呢?

  ? 記得咱們最開始介紹了可變對象和不可變對象,這里的n[0]是數(shù)值,是不可變對象,所以在地址不改變的情況下,它的值是不變的;

  ? 而我們在給它賦值時,相當(dāng)于是把它指向了另一個地址,存儲新值,而m[0]和p[0]指向的地址并沒有變化

  ?

  接下來咱們再來嘗試變更一下n[2]吧

print('----------------------------修改前----------------------------------\n ' ? ? ?f'm[2]的地址:{id(m[2])}\n n[2]的地址:{id(n[2])}\n p[2]的地址:{id(p[2])}') n[2][1] = 'n21'print('----------------------------修改后----------------------------------\n' ? ? ?f' m[2]={m[2]}\n n[2]={n[2]}\n p[2]={p[2]}')print(f' m[2]的地址:{id(m[2])}\n n[2]的地址:{id(n[2])}\n p[2]的地址:{id(p[2])}') 輸出:----------------------------修改前---------------------------------- m[2]的地址:2235118923976 n[2]的地址:2235118923976 p[2]的地址:2235118923976 ----------------------------修改后---------------------------------- m[2]=[2, 'n21', 4, [5, 6]] n[2]=[2, 'n21', 4, [5, 6]] p[2]=[2, 'n21', 4, [5, 6]] m[2]的地址:2235118923976 n[2]的地址:2235118923976 p[2]的地址:2235118923976

  ? 可以看到,變更前后n[2]、m[2]和p[2]的地址都是沒變的, 原因你已經(jīng)知道了吧,是的,因為n[2]是可變對象,是可以在地址中直接變更值的。

?

  2. 深拷貝

   深拷貝完全父對象與子對象??墒褂胏opy模塊的deepcopy()方法進(jìn)行深拷貝,此外使用for循環(huán)復(fù)制可迭代序列也是深拷貝

m = [1, 0, [2, 3, 4, [5, 6]]] n1 = copy.deepcopy(m)print(f'對象m的地址是{id(m)},對象n1的地址是{id(n1)}')print(f'm[0]的地址是{id(m[0])},n1[0]的地址是{id(n1[0])}')print(f'm[2]的地址是{id(m[2])},n1[2]的地址是{id(n1[2])}') 輸出: 對象m的地址是2551218893640,對象n1的地址是2551219173192 m[0]的地址是140727516494912,n1[0]的地址是140727516494912 m[2]的地址是2551218833480,n1[2]的地址是2551221308040

  ? ?打印結(jié)果可以看出,新舊對象本身的地址,和可變子對象地址都是不同的。

  ? ?這里看到m[0]和n1[0]的地址相同,但不可變對象的值變更地址就會變更,所以不會有問題。

?

三、 總結(jié)

  綜上,咱們在實際應(yīng)用中,如果拷貝對象的子對象都是不可變對象,那么使用淺拷貝和深拷貝都行,

  但如果待拷貝對象中有可變子對象,需要注意根據(jù)實際需求選擇使用深拷貝還是淺拷貝。


淺顯直白的Python深拷貝與淺拷貝區(qū)別說明的評論 (共 條)

分享到微博請遵守國家法律
卢龙县| 高平市| 吴堡县| 鄂托克前旗| 广汉市| 普洱| 方正县| 甘孜县| 成安县| 青浦区| 通许县| 陇川县| 甘孜| 舟山市| 星子县| 孝昌县| 曲靖市| 达日县| 革吉县| 扶风县| 留坝县| 商南县| 黄陵县| 凤山县| 平乐县| 宾川县| 宾阳县| 文登市| 乐清市| 舞钢市| 大田县| 平陆县| 岐山县| 普兰县| 剑阁县| 三门县| 乐昌市| 开化县| 正定县| 武胜县| 溧阳市|