所有Python對象都有三個屬性:身份、類型、值
name='a'
id(name) #id-身份唯一標識
type(name) #對象類型
1.可變對象
列表、字典、集合,指可變對象的值可變,身份不變
2.不可變對象
數字、字符串、元組對象身份和值都不可變。新創建對象被關聯到原來變量名,舊對象被丟棄,垃圾回收器會在適當時機回收這些對象
3.引用
Python程序中每個對象都會在內存區域中申請一塊空間來保存,該對象在內存中所在位置地址被稱爲引用。開發程序時所定義的變量名實際是對象地址引用,引用是內存中的一個數字地址編號,使用對象時只要知道該對象的地址,就可操作這個對象,但因爲數字地址不方便在開發時使用和記憶,所以使用變量名形式來代替對象數字地址。Python中變量就是地址的一種表示形式,並不新開闢存儲空間
就像IP地址,訪問網站時實際都是通過IP地址確定主機,而IP地址不方便記憶,所以使用域名代替IP地址,使用域名訪問網站時被解析成IP地址使用
age=18
id(age)
Out: 1730306752
id(18)
Out: 1730306752
賦值的本質是讓多個變量同時引用同一個對象的地址
4.淺拷貝
只拷貝父對象,不拷貝對象內部中的子對象
不可變對象:
不可變對象只在修改時纔會在內存中開闢新空間,而拷貝實際上是讓多個對象同時指向一個引用,和對象賦值沒區別
import copy
a=10
b=copy.copy(a)
id(a)
Out:1730306496
id(b)
Out:1730306496
可變對象:
可變對象拷貝會在內存中開闢一個新空間來保存拷貝數據。當再改變之前對象時,對拷貝之後的對象沒有任何影響
import copy
l1=[1,2,3]
l2=copy.copy(l1) #l2=l1[:] 利用切片完成淺拷貝
id(l1)
Out:1916631742088
id(l2)
Out:1916636282952
l1[0]=11 #數字爲不可變對象
id(l1)
Out:1916631742088
id(l2)
Out:1916636282952
l1 #[11,2,3]
l2 #[1,2,3]
l1=[1,2,3]
l2=l1
id(l1)
Out: 1916633584008
id(l2)
Out: 1916633584008
l1[0]=11
id(l1)
Out: 1916633584008
id(l2)
Out: 1916633584008
print(l1,l2) #[11,2,3] [11,2,3]
複雜對象在拷貝時並沒有解決數據在傳遞之後的數據改變問題。原因是copy函數在拷貝對象時只是將指定對象的所有引用拷貝一份,如果這些引用當中包含一個可變對象(如列表),那麼數據還是會被改變。這種拷貝方式稱爲淺拷貝
a=[1,2]
l1=[3,4,a]
l2=copy.copy(l1)
id(l1)
Out:1916631704520
id(l2)
Out:1916631713736
a[0]=11
id(l1)
Out:1916631704520
id(l2)
Out:1916631713736
l1
Out:[3,4,[11,2]]
l2
Out:[3,4,[11,2]]
5.深拷貝
區別於淺拷貝只拷貝頂層引用,深拷貝會逐層進行拷貝,直到拷貝的所有引用都是不可變引用爲止(拷貝對象及其子對象)
import copy
a=[1,2]
l1=[3,4,a]
l2=copy.deepcopy(l1)
id(l1)
Out:1916632194312
id(l2)
Out:1916634281416
a[0]=11
id(l1)
Out:1916632194312
id(l2)
Out:1916634281416
l1
Out:[3,4,[11,2]]
l2
Out:[3,4,[1,2]]
6.淺拷貝優勢
1.時間角度:淺拷貝花費時間更少
2.空間角度:淺拷貝花費內存更少
3.效率角度:淺拷貝只拷貝頂層數據,一般情況下比深拷貝效率高