Python 入門指南 5.0
單元 11 - 進一步講指派與相等運算
Python 中都是物件 (object) ,物件分為可變 (mutable) 與不可變 (immutable) 兩種,可變的表示可以改變其內容,像是串列 (list) 、集合 (set) 、字典 (dictionary) 都可以附加、刪除或更換元素,不可變就是不能對內容做任何修改
下表為目前介紹過可變的資料型態 (data type) ,這些型態名稱都是 Python 內建的識別字 (identifier)
型態名稱 | 中文名稱 |
---|---|
list | 串列 |
set | 集合 |
dict | 字典 |
至於其他介紹過的資料型態都是不可變的,如下表
型態名稱 | 中文名稱 |
---|---|
bool | 布林 |
int | 整數 |
float | 浮點數 |
complex | 複數 |
str | 字串 |
tuple | 序對 |
range | range |
簡單說,如果先後用兩個變數 (variable) 分別建立相同的不可變資料型態數值,例如下圖變數 a 跟變數 b 都是指派為整數 1
連續兩個等號判斷數值是否相等,結果是回傳 True ,關鍵字 is 則可用來判斷兩個變數是否是相同物件,結果也是回傳 True , is 回傳 True 的原因是兩個 id() 的回傳值相同,因為 id() 會回傳物件起始的記憶體位置,既然起始的記憶體位置相同的話,那就會是相同的物件。
但是浮點數 (floating-point number) 包括可含有浮點數的複數會有點複雜,因為浮點數建立過程經過電腦模擬計算,建立一次就會模擬計算一次,也就是會重新建立一次物件,如下圖,兩個浮點數變數會是不同的物件
但是如果是將變數 a 直接指派給變數 b ,變數 a 跟變數 b 就會是相同的物件,如下圖
基本上 Python 中的數字型態都是不可變的,由於浮點數與複數都歸類為數字,再加上跟整數一樣都只有一個值,如果要改變都只能重新指派變數值。
以上是討論如將兩個變數指向相同的物件,指派運算還可以加入 if 條件檢查來決定指派的數值,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # 設定變數 n 同時檢查型態
n = 10 if type(10) == int else None
# 印出變數 n
print(n)
# 設定變數 n 同時檢查型態
n = 10 if type(10) == str else None
# 印出變數 n
print(n)
# 檔名: assign_demo01.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月
|
第 2 行在指派運算後加上 if 陳述,以條件檢查整數 10 是否為整數型態,如果是,變數 n 會順利被指派為整數 10 ,否則會被指派為 None ,由於 10 是整數沒錯,所以 n 會被設定為整數 10
2 | n = 10 if type(10) == int else None
|
第 6 行再做一次,不過條件檢查整數 10 是否為字串 (string) 型態,這樣變數 n 就會被指派為 None
6 | n = 10 if type(10) == str else None
|
此例執行結果如下
$ python assign_demo01.py |
10 |
None |
$ |
指派還有個特殊情況,一般來說, Python 的指派都是以陳述 (statement) 為主,也就是說,等號並不能放入其他的陳述當作運算式 (expression) ,但是針對需要指派運算式的情況, Python 允許用 := 單獨寫指派運算式 (assignment expression) ,例如
1 2 3 4 5 6 7 8 9 10 11 12 | # 以下條件含有指派運算式
if (i := -22) > 0:
# 如果條件為真就印出提示訊息
print("-22 大於 0")
# if 陳述結束後印出 i
print(i)
# 檔名: assign_demo02.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月
|
:= 因為排列像是海象的眼睛與長牙,因此又被稱為海象運算子 (walrus operator) 。
第 2 行,這裡的指派是放到 if 陳述的條件中,先把 i 指派為 -22 ,再判斷變數 i 是否大於 0
2 | if (i := -22) > 0:
|
此例執行結果如下
$ python assign_demo02.py |
-22 |
$ |
注意 := 必須包含在其他陳述內,不能單獨作為陳述,因此通常會用小括弧圍起來。
接下來我們回到可變的資料型態,以下用串列為例來看看指派的情況
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # 設定變數 data 為串列
data = [1, 2, 3]
# 將 data 指派給 new_data
new_data = data
# 判斷 data 與 new_data 是否有相同的內容
if new_data == data:
print("單純指派有相同的內容")
# 判斷 data 與 new_data 是否為相同的物件
if new_data is data:
print("單純指派是相同的物件")
# 將 data 的內容拷貝給 new_data
new_data2 = data.copy()
# 判斷 data 與 new_data 是否有相同的內容
if new_data2 == data:
print("單純拷貝有相同的內容")
# 判斷 data 與 new_data 是否為相同的物件
if new_data2 is data:
print("單純拷貝是相同的物件")
else:
print("單純拷貝不是相同的物件")
# 檔名: assign_demo03.py
# 說明:《Python入門指南》的範例程式
# 網站: http://kaiching.org
# 作者: 張凱慶
# 時間: 2023 年 5 月
|
以上 new_data 是被 data 指派,而 new_data2 則是被 data.copy() 指派
12 | new_data2 = data.copy()
|
兩者有何不同呢?我們先來看看執行結果如下
$ python assign_demo03.py |
單純指派有相同的內容 |
單純指派是相同的物件 |
單純拷貝有相同的內容 |
單純拷貝不是相同的物件 |
$ |
簡單說,如果是指派,兩個變數都連結到相同的物件,因此運用任何一個變數都能操作及修改該物件,但是如果用串列的 copy() 方法再指派,那是把元素內容拷貝建立一個新的串列給被指派的變數。
所以對串列來說,如果相同的物件連結到不同的變數,那就直接用變數來指派,反之如果需要的是單純拷貝為新的物件,那就要用 copy() 方法進行拷貝。
其實以上不是很好理解,但是需要慢慢弄懂,因為這是深入 Python 程式設計總是會碰到的問題,接下來我們回到介紹模組化 (modular design) 程式設計的第二步,也就是介紹如何定義類別 (class) 。
中英文術語對照 | |
---|---|
指派運算式 | assignment expression |
類別 | class |
資料型態 | data type |
字典 | dictionary |
浮點數 | floating-point number |
運算式 | expression |
識別字 | identifier |
不可變 | immutable |
串列 | list |
模組化 | modular design |
可變 | mutable |
物件 | object |
集合 | set |
陳述 | statement |
字串 | string |
海象運算子 | walrus operator |
變數 | variable |
重點整理 |
---|
1. Python 中的物件分成可變的與不可變的。。 |
2. 可變的資料型態有串列、集合、字典等。 |
3. 不可變的資料型態有布林、整數、浮點數、複數、字串、序對、 range 等。 |
4. 指派運算可以加入 if-else 來檢查,提供其他的指派選項。 |
5. 指派運算式可以放入其他陳述中進行指派動作。 |
6. 對可變的資料型態,直接指派會是相同的物件,如果呼叫 copy() 後指派,就會有相同內容但是不同的物件。 |
問題與討論 |
---|
1. 兩個變數如果有相同的內容,如何分辨兩個變數是不是同一個物件? |
2. 如何對指派數值進行條件檢查,好讓指派的數值符合需求? |
3. 什麼是指派運算式?指派運算式有什麼限制? |
練習 |
---|
1. 寫一個程式 exercise1101.py ,裡頭建立兩個空集合變數,先判斷是否有相同的內容,再判斷是否為相同的物件,如果相同就印出相對應的訊息。 參考程式碼 |
2. 寫一個程式 exercise1102.py ,裡頭建立兩個空字串變數,先判斷是否有相同的內容,再判斷是否為相同的物件,如果相同就印出相對應的訊息。 參考程式碼 |
3. 寫一個程式 exercise1102.py ,裡頭建立兩個浮點數變數,兩者都指派為 0.0 ,先判斷是否有相同的內容,再判斷是否為相同的物件,如果相同就印出相對應的訊息。 參考程式碼 |
4. 承接上一單元的練習 3 ,將新程式寫在 exercise1104.py 中,加入對參數重新指派並檢查參數是否為整數,如果不是整數就回傳 None 。 參考程式碼 |
5. 承接上一單元的練習 5 ,將新程式寫在 exercise1105.py 中,加入對參數重新指派並檢查參數是否為整數,如果不是整數就回傳 None 。 參考程式碼 |
6. 承接上一單元的練習 17 ,將新程式寫在 exercise1106.py 中,加入對參數重新指派並檢查參數是否為整數,如果不是整數就產生 None 。 參考程式碼 |
7. 承接上一單元的練習 7 ,將新程式寫在 exercise1107.py 中,加入對參數重新指派並檢查參數是否為整數,如果不是整數就回傳 None 。 參考程式碼 |
8. 承接上一單元的練習 18 ,將新程式寫在 exercise1108.py 中,加入對參數重新指派並檢查參數是否為整數,如果不是整數就產生 None 。 參考程式碼 |
9. 承接單元 6 的練習 8 ,將新程式寫在 exercise1109.py 中,將 score 的指派放到 if 之後的條件中。 參考程式碼 |
10. 承接單元 7 的練習 7 ,將新程式寫在 exercise1110.py 中,將使用者輸入及判斷結束條件都放到 while 之後的條件中。 參考程式碼 |