Python中的淺拷貝和深拷貝

2021-10-03 05:27:08 字數 2498 閱讀 6176

寫python**時,淺拷貝和深拷貝是經常遇見的問題,今天看書時碰到,結合書上的例子,再次整理一遍。例子來自《流暢的python》

>>

> l1 =[3

,[55,

44],(

7,8,

9)]>>

> l2 =

list

(l1)

#使用list型別內建的型別構造方法來複製列表l1

>>

> l2[3

,[55,

44],(

7,8,

9)]>>

> l2 == l1

true

>>

> l2 is l1

false

首先明確,在python中,賦值操作的原理是先建立物件(python一切皆物件),然後將左值作為右值的引用繫結在一起。

上面的**使用list內建的構造方法完成了對列表l1的複製,得到了副本l2。l1和l2的值是相等的(使用』=='運算子來判斷得到),但是l2和l1是兩個不同的物件(有is運算子得到)。除了類內建的構造方法,語句l2 = l1[:]也可以建立副本l2。

!!!這裡構造方法或[:]做的都是淺複製(即複製了最外層容器,但是副本中的元素是原容器中元素的引用)。如果所有元素都是不可變的(例如原子不可變資料型別:str,bytes和數值型別),那麼這樣沒有問題,還能節省記憶體。但是,對於可變資料型別(如列表等),這樣的引用就很容易出現問題。

l1 =[3

,[66,

55,44]

,(7,

8,9)

]l2 =

list

(l1)

# l2是l1的淺複製副本;

100)

# 最外層容器是不同的物件,對l2沒有影響;

l1[1

],remove(55)

# l2[1]是l1[1]的引用,本質是同乙個物件;

print

('l1'

, l1)

print

('l2'

, l2)

l2[1]+=

[33,22

]# 對可變的物件來說,如l2[1]引用的列表,+=運算子就地修改列表。這次修改在l1[1]中也有體現,因為它是l2[1]的別名。

l2[2]+=

(10,11

)# 對元組來說,+=運算子建立乙個新元組,然後重新繫結給變數l2[2]。這等同於l2[2] = l2[2] + (10, 11)。現在,l1和l2中最後位置上的元組不是同乙個物件。

print

('l1'

, l1)

print

('l2'

, l2)

列印結果:

l1:[3,

[66,44

],(7

,8,9

),100]

l2:[3,

[66,44

],(7

,8,9

)]l1:[3,

[66,44

,33,22

],(7

,8,9

),100]

l2:[3,

[66,44

,33,22

],(7

,8,9

,10,11

)]

copy模組中提供的deepcopycopy函式能為任意物件做深拷貝淺拷貝

注意,一般來說,深複製不是件簡單的事。如果物件有迴圈引用,那麼這個樸素的演算法會進入無限迴圈。deepcopy函式會記住已經複製的物件,因此能優雅地處理迴圈引用,如下面所示:b引用a,然後追加到a中;deepcopy會想辦法複製a

>>

> a =[10

,20]>>

> b =

[a,30

]>>

>>

> a[10

,20,[

[...

],30]

]>>

>

from copy import deepcopy

>>

> c = deepcopy(a)

>>

> c[10

,20,[

[...

],30]

]

深複製有時可能太深了。例如,物件可能會引用不該複製的外部資源或單例值。此時可以通過實現特殊方法__copy__()和__deepcopy__(),控制copy和deepcopy的行為。

python中的淺拷貝和深拷貝

不得不說 python核心程式設計 是一本好書,看到其中一節做一下隨筆。在python中,當建立乙個物件後,然後把它賦給另乙個物件時,python並沒有去拷貝這個物件,而是拷貝了這個物件的引用。看不懂沒關係,我們看乙個例子。raw list first second 12 32 copy list ...

python中的深拷貝和淺拷貝

淺拷貝 copy 不拷貝物件的內容,僅僅拷貝子物件的引用 深拷貝 deepcopy 會連同拷貝子物件的記憶體,對子物件的修改不會影響源物件 下面用 來測試 import copy deftest copy 淺拷貝測試 a 10 20,5,6 b copy.copy a print a a,end t...

python中的淺拷貝和深拷貝

本篇介紹下python中的深拷貝和淺拷貝,主要從基本型別 類 不可變型別等方面進行介紹。1.介紹拷貝之前首先應該明白is和 的區別,即is表示同乙個物件,比較的是值 a 1000 b 1000 a b true a is bfalse class person object def init sel...