python資料結構之深淺拷貝
Python中深淺拷貝詳解
變數-引用-物件(可變物件,不可變物件)-切片-拷貝(淺拷貝,深拷貝)
變數:在Python中一切都是物件,比如:3,3.14,“Hello world”,【1,2,3,4】,{‘a’:1}….
輸出:
甚至連Type其本身也是物件,type物件
Python中的變數指物件的引用,Python是動態型別,程式執行時會根據物件的型別來確認變數到底是什麼型別
比如:a=3
其中變數a是物件3的一個引用。在程式內部,變數事實上是到物件記憶體空間的一個指標
變數:指一個元素,擁有指向物件的連線空間
物件:被分配的一個記憶體,儲存其所代表的值
引用:自動形成的從變數到物件的指標
共享引用:比如:
輸出:
可以看出變數a和b指向了同一個物件的記憶體空間
可變物件:在Python中指可以修改的物件,例如:列表,字典
不可變物件:在Python中指不能改變的物件,例如:字串、元組、數字
L1=[3,4,5,6,7,8,9]#L1變數指向一個可變物件:列表
L2=L1#將L1的值賦給L2後,兩者共同引用同一個物件
L1[0]=300#將L1列表中的第一個元素改變
print(L1,L2)
輸出:
#[300, 4, 5, 6, 7, 8, 9] [300, 4, 5, 6, 7, 8, 9]
可以看出改變L1之後,L2的值跟著改變了,如果不想讓L2跟著改變,可以採用切片或者拷貝的方法
L1=[2,3,4,5,6,7]
L2=L1[:]#切片操作
print(id(L1),id(L2))#切片後物件就不一樣了
L1[0]=200
print(L1,L2)#L1改變,L2不改變
輸出:
12966968 12965408
[200, 3, 4, 5, 6, 7] [2, 3, 4, 5, 6, 7]
切片:與使用索引來訪問單個元素類似,可以使用切片操作來訪問一定範圍內的元素。切片通過冒號隔開兩個索引來實現
拷貝:切片操作可以應用在所有的序列中,例如:列表、元組、字串,但是不能用在字典當中,對字典只能使用D.copy()方法或D.deepcopy()方法,深淺拷貝可以用在序列當中,也可以應用在字典中。
import copy
X = copy.copy(Y) #淺拷貝:只拷貝頂級的物件,或者說:父級物件
X = copy.deepcopy(Y) #深拷貝:拷貝所有物件,頂級物件及其巢狀物件。或者說:父級物件及其子物件
程式碼實現:
如果字典中只含有頂級物件
import copy
D={'age':20,'name':'zhangsan'}#原始字典
C1=copy.copy(D)#淺拷貝
C2=copy.deepcopy(D)#深拷貝
print(id(D),id(C1),id(C2))#三個不同物件
D['name']='lisi'#改變源字典
print(D,C1,C2)
輸出:
28681296 28681728 59780144
{'age': 20, 'name': 'lisi'} {'age': 20, 'name': 'zhangsan'} {'age': 20, 'name': 'zhangsan'}
#可以看出只改變了原始字典中的物件值
如果字典中含有巢狀物件
import copy
D={'name':{'first':'zhang','last':'san'},'jobs':['IT','HR']}#原始字典含有巢狀物件
C1=copy.copy(D)#淺拷貝
C2=copy.deepcopy(D)#深拷貝
D['jobs'][0]='data'#改變原始字典中的jobs子物件‘it'變為’data'
print(D,C1,C2)
輸出:
{'name': {'first': 'zhang', 'last': 'san'}, 'jobs': ['data', 'HR']} {'name': {'first': 'zhang', 'last': 'san'}, 'jobs': ['data', 'HR']} {'name': {'first': 'zhang', 'last': 'san'}, 'jobs': ['IT', 'HR']}
#可以看出淺拷貝受影響,深拷貝不受影響
結論:
深淺拷貝都是對源物件的複製,佔用的是不同的記憶體空間
如果源物件只含一級目錄,深淺拷貝不受影響
如果含多級目錄,淺拷貝受影響,深拷貝不受影響
切片屬於淺拷貝
= :地址相同;原值改變,值隨之改變
copy.copy() :可變型別(list、dict)地址不同;原值改變,值隨之改變
不變型別(tuple)地址相同;值不可變
copy.deepcopy():地址不同;原值改變,值不隨之改變
深淺拷貝的作用:
1,減少記憶體的使用
2,以後在做資料的清洗、修改或者入庫的時候,對原資料進行復制一份,以防資料修改之後,找不到原資料。
對於不可變物件的深淺拷貝:
不可變物件型別,沒有被拷貝的說法,即便是用深拷貝,檢視id的話也是一樣的,如果對其重新賦值,也只是新建立一個物件,替換掉舊的而已。
一句話就是,不可變型別,不管是深拷貝還是淺拷貝,地址值和拷貝後的值都是一樣的。
參考文獻:https://blog.csdn.net/u012377333/article/details/41956727