python的深拷貝和淺拷貝
阿新 • • 發佈:2018-01-05
內存區域 需要 不可變 python3 復制 deepcopy 原始的 pen -m
# 對象賦值 a = 'hello world' b = a print('a:',a,', b:',b) # a: hello world , b: hello world print(id(a)==id(b)) # True a = 'Hello World' print('a:',a,', b:',b) # Hello World , b: hello world print(id(a)==id(b)) # False a = 1 b = a print('a:',a,', b:',b) # a: 1 , b: 1 print(id(a)==id(b)) # True a = 2 print('a:',a,', b:',b) # a: 2 , b: 1 print(id(a)==id(b)) # False a = ['x','y',[1,2,3]] b = a print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3]] , b: ['x', 'y', [1, 2, 3]] print(id(a)==id(b)) # True a.append('hello') print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3], 'hello'] print(id(a)==id(b)) # True a[2].append(4) print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3], 'hello'] print(id(a)==id(b)) # True """ 所以在python中,對象的賦值都是進行對象引用(內存地址)傳遞,只要a的內存地址沒有變化,a和b的內容都會始終一樣。 """ a = ['x','y',[1,2,3]] b = a[:] print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3]] , b: ['x', 'y', [1, 2, 3]] print(id(a)==id(b)) # False print([id(i) for i in a]) # [2059734973832, 2059735268016, 2059766662792] print([id(i) for i in b]) # [2059734973832, 2059735268016, 2059766662792] a.append('hello') print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3], 'hello'] , b: ['x', 'y', [1, 2, 3]] print(id(a)==id(b)) # False a[2].append(4) print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3, 4], 'hello'] , b: ['x', 'y', [1, 2, 3, 4]] print(id(a)==id(b)) # False print('淺拷貝') # 淺拷貝 import copy a = ['x','y',[1,2,3,[4,5,6]]] d = copy.copy(a) print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3, [4, 5, 6]]] , b: ['x', 'y', [1, 2, 3, 4]] print(id(a)==id(b)) # False print([id(i) for i in a]) # [2640575102344, 2640603314864, 2640606922568] print([id(i) for i in b]) # [2640575102344, 2640603314864, 2640606922824] a[2].append(4) print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3, [4, 5, 6], 4]] , b: ['x', 'y', [1, 2, 3, 4]] tmp_list_a = a[2] print(id(tmp_list_a)) # 2640606922568 print([id(i) for i in tmp_list_a]) # [1434892752, 1434892784, 1434892816, 2640606922632, 1434892848] tmp_list_b = b[2] print(id(tmp_list_b)) # 2640606922824 print([id(i) for i in tmp_list_b]) # [1434892752, 1434892784, 1434892816, 1434892848] """ 所以在python(python3.6)中淺拷貝會將不可變元素的地址直接拷貝,而可變對象如list會用新的地址指向原list內存區域,相當於兩個不同的指針指向同樣的內存區。 """ # 深拷貝 import copy a = ['x','y',[1,2,3,[4,5,6]]] b = copy.deepcopy(a) print('a:',a,', b:',b) # a: ['x', 'y', [1, 2, 3, [4, 5, 6]]] , b: ['x', 'y', [1, 2, 3, [4, 5, 6]]] print(id(a)==id(b)) # False print([id(i) for i in a]) # [2460486303112, 2460486597296, 2460490204808] print([id(i) for i in b]) # [2460486303112, 2460486597296, 2460490204616] tmp_list_a = a[2] print(id(tmp_list_a)) # 2460490204808 print([id(i) for i in tmp_list_a]) # [1434892752, 1434892784, 1434892816, 2460490204872] tmp_list_b = b[2] print(id(tmp_list_b)) # 2460490204616 print([id(i) for i in tmp_list_b]) # [1434892752, 1434892784, 1434892816, 2460490204552] """ 深拷貝,就是會遞歸的進行拷貝,直到查找到原子類型。 """ # 補充: """ 對於拷貝有一些特殊情況: 對於非容器類型(如數字、字符串、和其他'原子'類型的對象)沒有拷貝這一說 也就是說,對於這些類型,如果元祖變量只包含原子類型對象,則不能深拷貝。 如下例子: """ a = (1,'x') b = copy.copy(a) print(id(a)==id(b)) #沒有拷貝 # True b = copy.deepcopy(a) print(id(a)==id(b)) #沒有拷貝 # True a = (1,'x',[2]) b = copy.copy(a) print(id(a)==id(b)) #沒有拷貝 # True b = copy.deepcopy(a) print(id(a)==id(b)) #拷貝 # False # 總結 """ * Python中對象的賦值都是進行對象引用(內存地址)傳遞 * 使用copy.copy(),可以進行對象的淺拷貝,它復制了對象,但對於對象中的元素,依然使用原始的引用. * 如果需要復制一個容器對象,以及它裏面的所有元素(包含元素的子元素),可以使用copy.deepcopy()進行深拷貝 * 對於非容器類型(如數字、字符串、和其他'原子'類型的對象)沒有被拷貝一說 * 如果元祖變量只包含原子類型對象,則不能深拷貝 """
python的深拷貝和淺拷貝