python淺拷貝與深拷貝使用方法詳解
淺拷貝和深拷貝在面試和日常的開發中都會經常遇到
我們就從 對象賦值、淺拷貝、深拷貝 三個方面來講
一、對象賦值
In [1]: list1 = [1, 2, ['a', 'b']] list2 = list1 print(list1) print(list2) [1, 2, ['a', 'b']] [1, 2, ['a', 'b']] In [2]: list1[0] = 3 print(list1) print(list2) [3, 2, ['a', 'b']] [3, 2, ['a', 'b']] In [3]: list2[1]=[1,2] print(list1) print(list2) [3, [1, 2], ['a', 'b']] [3, [1, 2], ['a', 'b']] In [4]: print(id(list1)) print(id(list2)) 1742901832264 1742901832264
結論:直接對象賦值,兩個對象的地址是一樣的,也就是這兩個變量指向是同一個對象,兩個變量會同步變化
二、淺拷貝
In [5]: import copy A = [1, 'a', ['a', 'b']] # B = A.copy() # 淺拷貝 B = copy.copy(A) # 淺拷貝 print(A) print(B) print(id(A)) print(id(B)) [1, 'a', ['a', 'b']] [1, 'a', ['a', 'b']] 1742901926344 1742901925512 兩個對象的內存地址不一樣,也就是不是同一個對象 In [6]: # 循環分別打印每個對象中的成員的地址 # 打印A for i in A: print("值 {} 的地址是:{}".format(i,id(i))) 值 1 的地址是:140724000563600 值 a 的地址是:1742860054320 值 ['a', 'b'] 的地址是:1742901889800 In [7]: # 循環分別打印每個對象中的成員的地址 # 打印B for i in B: print("值 {} 的地址是:{}".format(i,id(i))) 值 1 的地址是:140724000563600 值 a 的地址是:1742860054320 值 ['a', 'b'] 的地址是:1742901889800
int類型的1和字符串型的a都是不可變數據類型,不可變數據類型值一樣,地址一樣,值不一樣,地址就不一樣
列表[‘a’, ‘b’]是可變數據類型,可變數據類型是 變量中數據變的時候,地址不會變,值相同的兩個對象,地址是不一樣的,如果地址一樣,表示指的是同一個對象
現在 A[2] 和 B[2] 指向的是同一個地址,說明是同一個列表,一個改變,另外的一個也會同步改變
通常來講不可變元素包含:
int,float,complex,long,str,unicode,tuple
In [8]: # 在 A[2] 中增加元素 A[2].append(3) print(A) print(B) [1, 'a', ['a', 'b', 3]] [1, 'a', ['a', 'b', 3]] In [9]: # 向A中增加元素 A.append(3) print(A) print(B) [1, 'a', ['a', 'b', 3], 3] [1, 'a', ['a', 'b', 3]] In [10]: A[0]=2 print(A) print(B) [2, 'a', ['a', 'b', 3], 3] [1, 'a', ['a', 'b', 3]]
淺拷貝(copy.copy()):拷貝父對象,不會拷貝對象的內部的子對象,也就是子對象共用
如果子對象是不可變數據類型,那麼復制的對象和原來的對象互不影響
如果是可變數據類型,那麼復制的對象和原來的對象共用
In [11]: A[2]=[1,2] print(A) print(B) [2, 'a', [1, 2], 3] [1, 'a', ['a', 'b', 3]] In [12]: print(id(A[2])) print(id(B[2])) 1742901889416 1742901889800
可以看到 現在 A[2] 和 B[2] 的地址不一樣瞭,那麼他們就互不影響瞭
其實看兩個可變數據類型是否互相影響,就是看他們的地址是否一樣
三、深拷貝
In [13]: m = [1, 'a', ['a', 'b']] n = copy.deepcopy(m) print(m) print(n) print(id(m)) print(id(n)) [1, 'a', ['a', 'b']] [1, 'a', ['a', 'b']] 1742900283720 1742900260680 In [14]: # 循環分別打印每個對象中的成員的地址 # 打印m for i in m: print("值 {} 的地址是:{}".format(i,id(i))) 值 1 的地址是:140724000563600 值 a 的地址是:1742860054320 值 ['a', 'b'] 的地址是:1742900341320 In [15]: # 循環分別打印每個對象中的成員的地址 # 打印n for i in n: print("值 {} 的地址是:{}".format(i,id(i))) 值 1 的地址是:140724000563600 值 a 的地址是:1742860054320 值 ['a', 'b'] 的地址是:1742900283208
可以看到,m和n兩個對象本身的地址是不一樣的,
並且m和n中成員中的可變數據類型的地址也是不一樣的,所以它們兩個是完全互不影響的
''' 學習中遇到問題沒人解答?小編創建瞭一個Python學習交流群:711312441 尋找有志同道合的小夥伴,互幫互助,群裡還有不錯的視頻學習教程和PDF電子書! ''' In [16]: m[2].append(3) n[1]=5 print(m) print(n) [1, 'a', ['a', 'b', 3]] [1, 5, ['a', 'b']]
淺拷貝(copy.copy()):拷貝父對象,不會拷貝對象的內部的子對象,也就是子對象共用
- 如果子對象是不可變數據類型,那麼復制的對象和原來的對象互不影響
- 如果是可變數據類型,那麼復制的對象和原來的對象共用
深拷貝(copy.deepcopy()):完全拷貝父對象跟子對象,復制的對象和原來的對象互不相關
四、深入解析
1、b = a.copy(): 淺拷貝, a 和 b 是一個獨立的對象,但他們的子對象還是指向統一對象(是引用)。
2、b = copy.deepcopy(a): 深度拷貝, a 和 b 完全拷貝瞭父對象及其子對象,兩者是完全獨立的。
到此這篇關於python淺拷貝與深拷貝使用方法詳解的文章就介紹到這瞭,更多相關python淺拷貝與深拷貝內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- 淺析Python的對象拷貝和內存佈局
- Python中list列表的賦值方法及遇到問題處理
- Python 變量類型實例詳解
- python六種基本數據類型及常用函數展示
- NumPy-ndarray 的數據類型用法說明