淺談python 復制(深拷貝,淺拷貝)


博客參考:點擊這里

python中對象的復制以及淺拷貝,深拷貝是存在差異的,這兒我們主要以可變變量來演示,不可變變量則不存在賦值/拷貝上的問題(下文會有解釋),具體差異如下文所示

1.賦值:

1 a=[1,2,3]
2 b=a
3 a.append('3')
4 print 'b=',b

  實例輸出結果如下:

1 b= [1, 2, 3, '3']

  這兒我們只對列表a進行了操作,但列表b也隨之改變,根本原因是在進行賦值操作的時候,變量a與變量b指向了相同的內存地址,實例如下:

1 #coding=utf-8
2 a=[1,2,3]
3 b=a
4 print "變量a的內存地址:",id(a) #獲取變量的內存地址
5 print "變量b的內存地址:",id(b)
6 a.append(4)
7 print "變量a的內存地址:",id(a)
8 print "變量b的內存地址:",id(b)

輸出結果如下:

1 變量a的內存地址: 39012592
2 變量b的內存地址: 39012592
3 變量a的內存地址: 39012592
4 變量b的內存地址: 39012592

  以上結果可以看出進行賦值操作時變量與變量b的內存地址一致,故而在變量a值發生改變時,變量b的值也隨之改變。

  但這種情況只針對可變變量,str屬於不可變變量,值發生改變的時候會重新申請新的地址,實例如下:

1 #coding=utf-8
2 a='123'
3 print ' 變量a的內存地址:',id(a)
4 a='234'
5 print ' 變量a的內存地址:',id(a)

  輸出結果如下:

1  變量a的內存地址: 38734832
2  變量a的內存地址: 38734856

2.淺拷貝(copy.copy())

1 #coding=utf-8
2 import copy
3 a=[1,2,3]
4 b=copy.copy(a)
5 print ' 變量a的內存地址:',id(a)
6 print ' 變量b的內存地址:',id(b)
7 a.append(4)
8 print b

  輸出結果:

1  變量a的內存地址: 38160664
2  變量b的內存地址: 38203224
3 [1, 2, 3]

  因為變量a與變量b的內存地址不一樣,故而在變量a發生改變時,變量b未改變,但因為淺拷貝依然會使用原始變量中元素的地址,實例如下:

1 #coding=utf-8
2 import copy
3 a=[1,2,3]
4 b=copy.copy(a)
5 for i in  range(0,len(a)):
6     print ' 變量a中第%d的內存地址:%d'%(i,id(a[i]))
7 for i in  range(0,len(b)):
8     print ' 變量b中第%d的內存地址:%d'%(i,id(b[i]))

  輸出結果:

1  變量a中第0的內存地址:33860840
2  變量a中第1的內存地址:33860828
3  變量a中第2的內存地址:33860816
4  變量b中第0的內存地址:33860840
5  變量b中第1的內存地址:33860828
6  變量b中第2的內存地址:33860816

  由輸出結果可知,變量a和變量b中的元素的內存地址是一致的,當變量a中存在可變元素時,對可變元素進行更改,變量b依然會同時進行更改,實例如下:

1 #coding=utf-8
2 import copy
3 a=[1,2,3,[11,2,3]]
4 b=copy.copy(a)
5 print '變量a修改前,b的內容:',b
6 a[3].append(4)
7 print  '變量a修改后,b的內容:',b

  輸出如下:

1 變量a修改前,b的內容: [1, 2, 3, [11, 2, 3]]
2 變量a修改后,b的內容: [1, 2, 3, [11, 2, 3, 4]]

3.深拷貝(copy.deepcopy())

1 #coding=utf-8
2 import copy
3 a=[1,2,3,[11,2,3]]
4 b=copy.deepcopy(a)
5 for i in  range(0,len(a)):
6     print ' 變量a中第%d的內存地址:%d'%(i,id(a[i]))
7 for i in  range(0,len(b)):
8     print ' 變量b中第%d的內存地址:%d'%(i,id(b[i]))

  輸出如下:

1  變量a中第0的內存地址:30518504
2  變量a中第1的內存地址:30518492
3  變量a中第2的內存地址:30518480
4  變量a中第3的內存地址:38553880
5  變量b中第0的內存地址:30518504
6  變量b中第1的內存地址:30518492
7  變量b中第2的內存地址:30518480
8  變量b中第3的內存地址:38643072

  變量a與變量b中的每一個元素的內存地址都不相同,故而變量a發生改變時,變量b不會隨之改變。

總結:

  1.賦值,淺拷貝,深拷貝只針對可變變量,如list,dict,tuple

  2.python中賦值都是進行內存地址的傳遞

  3.淺拷貝(copy,copy())只會賦值對象,重新申請內存地址,但對於對象中的元素依然是原始的內存地址引用

  4.如果要完全拷貝一個對象,請使用copy.deepcopy()

 

 

 

寫在后面:

  每天寫一點,總有一天我這條咸魚能變得更咸


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM