不可變物件:該物件所指向的記憶體中的值不能被改變,修改物件的值時,由於其指向的值不能被改變,因此實際上是在記憶體中重新開闢乙個位址用來儲存新的值,然後將物件指向這個新值。本質上是兩個物件,賦值前後物件id發生了變化。python中的不可變物件包括:bool、int、str、float、tuple、frozenset、none。
淺拷貝:通常指構造乙個新的集合物件,然後用原始物件中的找到的子物件的引用來填充它。淺層的複製只有一層深度,複製過程中不會遞迴,所以不會建立子物件本身的副本。
案例1
import copy
lst = [[1,2],3,4]
new3_lst = copy.copy(lst)
print(id(lst), lst) # 2027983558024 [[1, 2], 3, 4]
print(id(new3_lst), new3_lst) # 2027983557000 [[1, 2], 3, 4]
==>先列印一下剛複製出來的兩個物件及記憶體編號
print('-------------------')
new3_lst[0][0] = 4
print(id(lst),lst) # 2027983558024 [[4, 2], 3, 4]
print(id(new3_lst),new3_lst) # 2027983557000 [[4, 2], 3, 4]
==>推出:改變拷貝物件的子物件的成員值,會同時影響原始物件和拷貝物件
print('-------------------')
new3_lst[2] = 0
print(id(lst),lst) # 2757271180296 [[4, 2], 3, 4]
print(id(new3_lst),new3_lst) # 2757271135560 [[4, 2], 3, 0]
==>推出:改變拷貝物件的第一層次的成員值,不會影響原始物件
print('-------------------')
lst[2] = 0
print(id(lst),lst) # 2757271180296 [[4, 2], 3, 0]
print(id(new3_lst),new3_lst) # 2757271135560 [[4, 2], 3, 0]
print('-------------------')
lst[0][0] = 9
print(id(lst),lst) # 2757271180296 [[9, 2], 3, 0]
print(id(new3_lst),new3_lst) # 2757271135560 [[9, 2], 3, 0]
==>推出:改變原始物件的成員或者子物件的成員值,拷貝物件的元素跟著改變
"""總結
淺拷貝,改變原始物件的成員或者子物件的成員值,拷貝物件的元素跟著改變
改變拷貝物件的子物件的成員值,會同時影響原始物件和拷貝物件
改變拷貝物件的第一層次的成員值,不會影響原始物件
"""
案例2
# example 1
lst = [[1,2],3,4]
new2_lst = list(lst)
print(id(lst)) # 2291852075656
print(id(new2_lst)) # 2291852075656
print('-------------------')
new2_lst[0][0] = 40
print(id(lst),lst) # 2364733153992 [[40, 2], 3, 4]
print(id(new2_lst),new2_lst) # 2364736713480 [[40, 2], 3, 4]
print('-------------------')
new2_lst[2] = 40
print(id(lst),lst) # 2364733153992 [[40, 2], 3, 4]
print(id(new2_lst),new2_lst) # 2364736713480 [[40, 2], 3, 40]
print('***********************')
lst[0][1] = 20
print(id(lst),lst) # 2364733153992 [[40, 20], 3, 4]
print(id(new2_lst),new2_lst) # 2364736713480 [[40, 20], 3, 40]
print('-------------------')
lst[2] = 30
print(id(lst),lst) # 2364733153992 [[40, 20], 3, 30]
print(id(new2_lst),new2_lst) # 2364736713480 [[40, 20], 3, 40]
"""總結
修改第一層次的成員值,不會影響拷貝物件;修改子物件的成員值(第二層次),會同時影響原始物件和拷貝物件
"""
深拷貝:深拷貝使複製過程遞迴,即首先構造乙個新的集合物件,然後遞迴地用在原始物件中找到的子物件的副本來填充它。通過深拷貝複製物件,是原始物件及其所有子物件的完全獨立的轉殖。
# 深拷貝: 拷貝物件及子物件(遞迴)
lst1 = [[1,2],3,4]
print('--------深拷貝--------')
import copy
new4_lst = copy.deepcopy(lst1)
print(id(lst1),lst1) # 1951550628552 [[1, 2], 3, 4]
print(id(new4_lst),new4_lst) # 1951582564552 [[1, 2], 3, 4]
==>先列印一下剛深拷貝出來的兩個物件及記憶體編號
print('-------------------')
# 改變新物件的子物件的成員值,不會影響原始物件
new4_lst[0][1] = 9
print(id(lst1),lst1) # 1951550628552 [[1, 2], 3, 4]
print(id(new4_lst),new4_lst) # 1951582564552 [[1, 9], 3, 4]
print('-------------------')
# 改變拷貝物件的第一層次的成員值,不會影響原始物件
new4_lst[1] = 10
print(id(lst1),lst1) # 1951550628552 [[1, 2], 3, 4]
print(id(new4_lst),new4_lst) # 1951582564552 [[1, 9], 10, 4]
print('-------------------')
# 改變原始物件的子物件的成員值,不會影響拷貝物件
lst1[0][1] = 20
print(id(lst1),lst1) # 1951550628552 [[1, 20], 3, 4]
print(id(new4_lst),new4_lst) # 1951582564552 [[1, 9], 10, 4]
print('-------------------')
# 改變原始物件的第一層次的成員值,不會影響拷貝物件
lst1[1] = 16
print(id(lst1),lst1) # 1951550628552 [[1, 20], 16, 4]
print(id(new4_lst),new4_lst) # 1951582564552 [[1, 9], 10, 4]
"""總結
深拷貝,新舊對像及其子物件的成員值完全獨立,互不影響
"""
總結 淺拷貝 深拷貝
copy mutablecopy copy 不管是可變的,還是不可變的,結果都是不可變的 mutablecopy 不管是不可變的,還是可變的,結果都是可變的 nsmutablestring str nsmutablestring stringwithformat a nsarray arr1 str...
深拷貝 淺拷貝
c 中物件的複製就如同 轉殖 用乙個已有的物件快速地複製出多個完全相同的物件。一般而言,以下三種情況都會使用到物件的複製 1 建立乙個新物件,並用另乙個同類的已有物件對新物件進行初始化,例如 cpp view plain copy class rect rect rect1 rect rect2 r...
淺拷貝 深拷貝
retain是建立乙個指標,引用物件計數加1。copy屬性表示兩個物件內容相同,新的物件retain為1 與舊有物件的引用計數無關,舊有物件沒有變化。copy減少物件對上下文的依賴。retain屬性表示兩個物件位址相同 建立乙個指標,指標拷貝 內容當然相同,這個物件的retain值 1也就是說,re...