博客參考:點擊這里
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()
寫在后面:
每天寫一點,總有一天我這條咸魚能變得更咸