python之淺拷貝與深拷貝

1. 淺拷貝

淺拷貝是對於一個對象的頂層拷貝 通俗的理解是:拷貝了引用,並沒有拷貝內容

In [10]: a = [11,22,33]    In [11]: b = a    In [12]: id(a)  Out[12]: 140343572333832    In [13]: id(b)  Out[13]: 140343572333832    In [14]: a[0] = 'aa'    In [15]: a  Out[15]: ['aa', 22, 33]    In [16]: b  Out[16]: ['aa', 22, 33]

當b = a時,實際上是將a列表的記憶體地址賦值給了b,那麼變數a與變數b指向的是同一記憶體地址!

2. 深拷貝

深拷貝是對於一個對象所有層次的拷貝(遞歸)

In [17]: import copy    In [18]: c = copy.deepcopy(a)    In [19]: id(a)  Out[19]: 140343572333832    In [20]: id(c)  Out[20]: 140343572336840    In [21]: a  Out[21]: ['aa', 22, 33]    In [22]: c  Out[22]: ['aa', 22, 33]    In [23]: a[0] = 11    In [24]: a  Out[24]: [11, 22, 33]    In [25]: c  Out[25]: ['aa', 22, 33]

深拷貝不僅拷貝引用還拷貝值,所以記憶體地址不一樣!

再看下面的程式碼,進一步理解淺拷貝與深拷貝:

注意:變數e由於用的是深拷貝,所以引用與值都是獨立的一份

copy.copy

上面演示了copy.deepcopy的用法,下面看copy.copy的用法:

In [40]: a = [1,2,3]    In [41]: b = [4,5,6]    In [42]: c = [a,b]    In [43]: e = copy.copy(c)    In [44]: a.append(4)    In [45]: c[0]  Out[45]: [1, 2, 3, 4]    In [46]: id(c)  Out[46]: 140343572344200    In [47]: id(e)  Out[47]: 140343588052232

圖解:

由於變數e用的是copy.copy(c)的方法,所以只拷貝了列表[a,b]的引用(copy.copy只能拷貝第一層引用),所以變數c與變數e的記憶體地址是不同的,但當改變[a,b]列表中a列表的值時,發現e變數中的a列表也會改變,說明copy.copy方法只拷貝了列表[a,b]列表的引用,而沒有拷貝列表[a,b]中列表a與列表b的引用。實際上列表[a,b]中的兩個列表a,b的記憶體地址還是指向的a與b

copy元組時的特點

copy.copy方法在copy時會自動判斷copy的對象是可變類型還是不可變類型,如果是不可變類型,那麼直接將引用指向copy的對象,如果是可變類型,那麼只拷貝第一層的引用,後面的引用不會拷貝