Python 列表的 賦值拷貝 淺拷貝與深拷貝

2021-10-04 17:39:45 字數 3979 閱讀 3682

一、文字說明:

在對原有列表進行操作的時候,很有可能會修改原有列表的值,所以根據需要在這之前最好先將原有列表拷貝乙份,在對它的副本進行操作,而原列表保持不變。這個時候就需要注意 如何拷貝 的問題,因為它牽扯到 對於你新拷貝出來的列表進行操作是否還是會修改原有列表的值。

通過學習,我有以下總結,對於列表一共有三種拷貝方法:

1.賦值拷貝。c=a,即通過』='號將a列表賦值給b列表。

這種列表方式要注意的是,它只是給a列表的位址新增加了乙個叫做c的標籤,也就是說a和c都指向的是同乙個列表位址,所以即便c是你拷貝後的列表,當你對c進行操作時,a也會發生一模一樣的變化。

2.通過b=a.copy()方法進行拷貝。(b=a[:]也是淺拷貝)

這種方式與第一種通過賦值進行拷貝的方式不同,它是新建了乙個位址用於存放拷貝後的列表,也就是說原列表a與通過a.copy()方式是存放在不同的位置,以我這個新手的理解,這樣的話,a與b可能從此就各自安好,各司其職 互不干擾了吧。 然而,世界遠比想象中的複雜。是的,測試了好多次,確實對於原列表進行操作後,新拷貝的列表都沒有發生變化。

但是!有乙個特殊的情況:如果,原列表中包含列表元素,一旦原列表中的該列表元素發生了變化,則通過copy方法得到的列表中該元素也會發生一樣的變化。

通過網上查閱資料,我的理解是,當原列表a中巢狀有其他列表ls時,這個作為原列表中乙個元素的巢狀列表ls,他自己有乙個自己的位址,而原列表a的位址只是對ls的位址進行了引用,通過copy雖然新建了乙個列表位址,但這個列表位址中對於巢狀列表ls的位址也只是複製了其引用,所以ls的位址作為乙個單獨的存在被原列表和copy複製後的列表b同時引用,所以當乙個變時,兩個都會發生變化。

那麼就沒有辦法通過拷貝,來形成乙個新的列表,還確保它自此以後和原列表沒有任何關係了嗎?

不是的。

3.通過import copy,使用copy.deepcopy(list),通過它來實現拷貝後原列表和新列表徹底無關係。

copy.deepcopy(list)是對原列表的全部的拷貝,連同他巢狀的列表的位址也一起進行了拷貝,而不像ls.copy()拷貝的只是他的引用。所以自此,原列表和新複製的列表無關了。

不知道理解的對不,還需要大家的檢驗和後續不斷的反思

二、**說明:

1.關於賦值=拷貝的**說明:

>>

> a=[1

,2,3

,['boy'

,'girl']]

>>

> b=a

>>

> a.

(10000

)>>

> a[1

,2,3

,['boy'

,'girl'],

10000

]>>

> b[1

,2,3

,['boy'

,'girl'],

10000

]>>

>

id(a)

4318318464

>>

>

id(b)

4318318464 #可以看出通過賦值=拷貝的列表和原列表位址一致,所以之後原列表和新列表也會一起變

>>

> a[3]

.(11111

)>>

> a[1

,2,3

,['boy'

,'girl'

,11111],

10000

]>>

> b[1

,2,3

,['boy'

,'girl'

,11111],

10000

]>>

>

id(a[3]

)4318317504

>>

>

id(b[3]

)4318317504 #可以看出原列表中巢狀的列表[

'boy'

,'girl'

,11111

]和新列表中的[

'boy'

,'girl'

,11111

]元素的位址是一樣的

2.關於a.copy()方法的**說明:

>>> a

[1, 2, 3, ['name', 'boy', 'girl']]

>>> c=a.copy()

>>> c

[1, 2, 3, ['name', 'boy', 'girl']]

>>> a

[1, 2, 3, ['name', 'boy', 'girl']]

>>> id(a[3])

4335438720

>>> id(c[3])

4335438720

# 這裡可以看出,通過a.copy()複製的列表中巢狀的列表['name', 'boy', 'girl'] 的位址與原列表中巢狀的['name', 'boy', 'girl']的位址一樣。都是4335438720

>>> id(a[0])

4315287600

>>> id(c[0])

4311550608 #這裡看出 對於原列表中其他非巢狀的元素,新舊兩個列表的位址是不一樣的。

>>> a.insert(0,'new')

>>> a

['new', 1, 2, 3, ['name', 'boy', 'girl']]

>>> c

[1, 2, 3, ['name', 'boy', 'girl']] #對原列表中加入新的元素,新複製的列表並沒有改變

>>> a[4].insert(0,'sun')

>>> a

['new', 1, 2, 3, ['sun', 'name', 'boy', 'girl']]

>>> c

[1, 2, 3, ['sun', 'name', 'boy', 'girl']] #由於新舊列表中巢狀的列表['name', 'boy', 'girl'] 的位址一樣,對列表中巢狀的列表進行修改時,新舊列表同時被修改。(都加入了'sun')

3.通過import copy,使用copy.deepcopy(list)進行深拷貝

>>

> a=[1

,2,3

,['boy'

,'girl']]

>>

> import copy

>>

> d=copy.

deepcopy

(a)>>

> a[1

,2,3

,['boy'

,'girl']]

>>

> d[1

,2,3

,['boy'

,'girl']]

>>

>

id(a[3]

)4335438720

>>

>

id(d[3]

)4318327808 #從這看出來 原列表 a 和 通過copy.

deepcopy

(a)得到的新列表d雖然看起來一模一樣,但是他們內嵌的列表[

'boy'

,'girl'

]的位址並不一樣。

>>

> a[3]

.insert(0

,'name'

)>>

> a[1

,2,3

,['name'

,'boy'

,'girl']]

>>

> d[1

,2,3

,['boy'

,'girl'

]] #對a的操作並沒有影響d.

>>

>

87907221

js 淺拷貝直接賦值 js的賦值與淺拷貝 深拷貝

昨天翻了下陣列api,看到concat和slice方法,突然想到這個兩個方法是淺拷貝還是深拷貝,結果陷入了死胡同,為什麼mdn文件說是淺拷貝,但進行簡單的操作為什麼能複製成功啊,糾結半天後才弄清原由,原來我一直把賦值和深淺拷貝搞混了。首先不要把引用型別的賦值歸結為淺拷貝,深拷貝和淺拷貝只針對像 ob...

Python 列表賦值 淺拷貝 深拷貝 02

關於python中列表 字典的深淺拷貝問題之前認識比較模糊,之前的筆記中其實只是區分了拷貝和賦值的問題,今天以列表為例重新學習一下 關於深淺拷貝和賦值的概念 a.直接賦值 用等號 其實就是物件的引用 b.淺拷貝 用copy 拷貝父物件,但是不會拷貝內部子物件 c.深度拷貝 用deepcopy,是採用...

Python 賦值 淺拷貝 深拷貝

賦值 a b,只拷貝了物件的引用,沒有拷貝內容。兩個物件的id一樣 淺拷貝 copy.copy 構造乙個新的復合物件,然後將子物件引用插入到原始物件的副本中。深拷貝 copy.deepcopy 構造乙個新的復合物件,然後遞迴地將子物件副本插入原始物件的副本。給個栗子 從這個栗子可以看出,對c進行修改...