Python基礎 第20節 深淺copy

2022-05-06 21:42:09 字數 4039 閱讀 3669

l1 = [1, 2, 'conan', [11, 22]]

l2 = l1

l1[0] = 111

print(l1) # [111, 2, 'conan', [11, 22]]

print(l2) # [111, 2, 'conan', [11, 22]]

print(id(l1[0])) # 1872924208

print(id(l2[0])) # 1872924208

print(l1) # [111, 2, 'conan', [11, 22], 333]

print(l2) # [111, 2, 'conan', [11, 22], 333]

print(id(l1)) # 2211423993544

print(id(l2)) # 2211423993544

print(l1) # [111, 2, 'conan', [11, 22, 666], 333]

print(l2) # [111, 2, 'conan', [11, 22, 666], 333]

print(id(l1[3])) # 2211453800136

print(id(l2[3])) # 2211453800136

​ 從上面的執行結果可以看到, 對於賦值運算來說, l1與l2指向的是同乙個記憶體位址, 所以它們是完全一樣的. 其中乙個變數對列表進行改變, 剩下的變數在使用列表時, 就是使用的改變之後的列表.

# 同一**塊下

l1 = [1, 2, 'conan', [11, 22]]

l2 = l1.copy()

l1[0] = 111

print(l1) # [111, 2, 'conan', [11, 22]]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1[0])) # 1872924208

print(id(l2[0])) # 1872920688

print(id(l1[1])) # 1872920720

print(id(l2[1])) # 1872920720

print(l1) # [111, 2, 'conan', [11, 22], 333]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1)) # 2343138115272

print(id(l2)) # 2343138954824

print(l1) # [111, 2, 'conan', [11, 22, 666], 333]

print(l2) # [1, 2, 'conan', [11, 22, 666]]

print(id(l1[3])) # 2343138954952

print(id(l2[3])) # 2343138954952

# 不同**塊下

l1 = [1, 2, 'conan', [11, 22]]

l2 = l1.copy()

l1[0] = 111

print(l1) # [111, 2, 'conan', [11, 22]]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1[0])) # 1872924208

print(id(l2[0])) # 1872920688

print(id(l1[1])) # 1872920720

print(id(l2[1])) # 1872920720

print(l1) # [111, 2, 'conan', [11, 22], 333]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1)) # 2402040017736

print(id(l2)) # 2402040018120

print(l1) # [111, 2, 'conan', [11, 22, 666], 333]

print(l2) # [1, 2, 'conan', [11, 22, 666]]

print(id(l1[3])) # 2402040003848

print(id(l2[3])) # 2402040003848

對於淺copy來說, 只是在記憶體中重新開闢了乙個空間存放乙個新列表, 但是新列表裡面的元素與原列表裡面的元素的記憶體位址是同乙個. 所以, l1與l2的id不同, 但是裡面內容的id是相同的.

注意

我們發現, 在更改l1的第乙個元素, 也就是把 1 改為 111 之後, 記憶體位址是不一樣的, 這是因為int型別是不可變的資料型別; 而列表時可變的資料型別, 當裡面的列表增加乙個元素後, 其記憶體位址是不變的.

依舊是先看下**

import copy

l1 = [1, 2, 'conan', [11, 22]]

l2 = copy.deepcopy(l1)

l1[0] = 111

print(l1) # [111, 2, 'conan', [11, 22]]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1[0])) # 1872924208

print(id(l2[0])) # 1872920688

print(id(l1[1])) # 1872920720

print(id(l2[1])) # 1872920720

print(l1) # [111, 2, 'conan', [11, 22], 333]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1)) # 2698658605000

print(id(l2)) # 2698660016776

print(l1) # [111, 2, 'conan', [11, 22, 666], 333]

print(l2) # [1, 2, 'conan', [11, 22]]

print(id(l1[3])) # 2698659950152

print(id(l2[3])) # 2698660016712

對於深copy來說, 深copy後的列表是在記憶體中重新建立的. 而且python為了節省記憶體以及提高效能, 它做了這麼一件事:

在深copy後的列表中,

如果其元素是可變的資料型別就再重新建立乙個;

如果其元素是不可變的資料型別, 就公用乙個, 也就是其記憶體位址是一樣的.

在上面**中的執行結果也能看出來.

淺copy: 巢狀的可變的資料型別 是 同乙個.

深copy: 巢狀的可變的資料型別 不是 同乙個.

寫出下面**的執行結果

l1 = [1, 2, 3, ['conan']]

l2 = l1[::]

print(l1)

print(l2)

l1: [1, 2, 3, ['conan', 666]]

l2: [1, 2, 3, ['conan', 666]]

通過列印其id可以發現,l2 = l1[::]的操作其實與淺copy一樣.

Python基礎 深淺拷貝

import copy num 0 copy num copy.copy num print these are normal copy center 60,print num,id num print copy num,id copy num print these are deep copy c...

第20節 C 委託與事件學習

主程式啟動類 委託的測試類 using system using system.collections.generic using system.text namespace 委託與事件認識 註冊委託類 委託的註冊 using system using system.collections.gene...

Python開發 第5節 函式基礎

函式的本質就是功能的封裝。函式的作用 def 函式名 引數 函式文件 函式功能 函式功能 呼叫函式 函式名 引數 形參 宣告函式時 中的引數是形參 形參只有在被呼叫時才分配記憶體單元,在呼叫結束時,即刻釋放所分配的記憶體單元。形參只在函式內部有效。函式呼叫結束返回主呼叫函式後則不能再使用該形參變數。...