1. 程式人生 > >Python走過的坑,可變不可變資料型別

Python走過的坑,可變不可變資料型別

Python走過的坑,可變不可變資料型別

Python標準資料型別

  1. Number(數字)
  2. String(字串)
  3. Dictionary(字典)
  4. List(列表)
  5. Tuple(元組)
  6. Set(集合)

Python不可變資料型別(一個蘿蔔一個坑)

比如數字,字串,元組。這是什麼意思呢,show your code:

a = 1
print("變數a在記憶體當中的地址":,id
(a)) a += 1 print("變數a在記憶體當中的地址":,id(a))

結果為

變數a在記憶體當中的地址 1683713088
變數a在記憶體當中的地址 1683713120

可以看到,變數a在記憶體當中的地址發生了變化,多了32個bit,也就是4個位元組,這裡說句題外話,在python中int代表的是長整型,沒有 python2 中的 Long。
換句話說,一個數字對應一個記憶體地址,數字變,地址變,一個蘿蔔一個坑。
還有一個要注意的地方。

a = 1
print("變數a在記憶體當中的地址":,id(a))	
b = 1
print("變數a在記憶體當中的地址"
:,id(b))

結果為:

變數a在記憶體當中的地址 1683713088
變數a在記憶體當中的地址 1683713088

一模一樣的,這說明了什麼,說明了變數a和b指向了同一塊內容,其實就是同一個物件的不同引用,也就是同一個人的不同名字而已。或者還是拿蘿蔔來說。一個坑裡,只能長一個蘿蔔,中國人叫蘿蔔,老外管它叫turnip(蘿蔔的英文),這下懂了吧。

可變資料型別(一塊地好多蘿蔔)

典型的就是列表,這個可吃了不少虧。
來吧

a = [1,2,3]
print("變數a在記憶體當中的地址":,id(a))	
a.append(4)
print("變數a在記憶體當中的地址"
:,id(a))

結果為

變數a在記憶體當中的地址 2635029663240
變數a在記憶體當中的地址 2635029663240

可以看到,一毛一樣啊。這就相當於在原來的地裡又長了一個蘿蔔,當然也許是又長了白菜,土豆什麼的內建的資料型別,或者是自定義的資料型別等等。
比如a = [1,2,3,“白菜”]
來一張圖更形象一點。一個矩形的土地,長了3個蘿蔔。

然後又扔過去一個白菜。
在這裡插入圖片描述
地還是那塊地(記憶體地址並沒有發生改變),但是其中元素增加了。
總結為:元素變,地址不變,同一塊地可以種好多蘿蔔,這就是可變資料型別。
這裡也有一個值得注意的問題:
come on code!

a = [1,2,[3,4]]
print('a = :',a)
b = a 
b[2] = [5,6]
print('a = ',a)

結果為:

a =  [1, 2,[3, 4]]
a =  [1, 2, [5, 6]]

這裡a和b所指的是同一個東西,也就是說,a和b都是[1,2,[3,4]]這個列表的引用,也就是外號。一般我們在記憶體中建立了一個列表,有兩種情況:

  1. 需要建立一個此列表的副本,一個一模一樣的列表,只不過在記憶體中多開闢了一塊空間來。這樣做的好處是,對副本所做修改不會影響到原來的列表,因為有時候我們需要原列表與修改後的列表進行對比。需要建立一個此列表的副本,一個一模一樣的列表,只不過在記憶體中多開闢了一塊空間來。這樣做的好處是,對副本所做修改不會影響到原來的列表,因為有時候我們需要原列表與修改後的列表進行對比。比如:
a = [1,2,[3,4]]
b = a.copy()
a[2][-1] = 'x'
print(a)#結果為[1, 2, [3, 'x']]
print(b)#結果為[1, 2, [3, 'x']]

咦,不對呀,我明明建立了一個原列表的副本啊,怎麼對a修改,b也會跟著修改呢?這是因為淺複製,深複製的問題,如果列表只有一層,那麼用淺複製足夠了。但是我們做專案的時候,動不動就好幾層的list,因此,必須採用深複製。下面是例項程式碼:

import copy
a = [1,2,[3,4]]
b = copy.deepcopy(a)
a[2][-1] = 'x'
print(a)#結果為[1, 2, [3, 'x']]
print(b)#結果為[1, 2, [3, 4]]

這樣,就可以完完全全地複製一個列表了。有個部落格對這種情況說的挺好的,
開啟連結,有句話是這麼說的,因為淺複製 ,複雜子物件的儲存方式是作為引用方式儲存的,所以修改淺複製的值和原來的值都可以改變複雜子物件的值。
2. 只需另外再建立一個對列表物件的引用即可,這種情況不需要原列表與修改後的列表進行對比,當列表比較大,又使用不到以前版本的列表時,推薦使用這種方式,節省記憶體。比如

a = [1,2,3]
b = a