最近重新整理之前的 Python 基本語法筆記, 由於篇幅太長編修時載入時間較久, 決定將流程控制與分割出來. 本系列前一篇文章參考 :
本篇繼續整理與測試 Python 基本語法之流程控制 :
八. 流程控制 :
結構化程式設計主要包括下列三種語法結構 :
1. 分支 (branch) :
分支使用條件式控制程式的執行方向, 語法如下 :
if 條件式1 :
分支區塊1
[elif 條件式2 :
分支區塊2]
[elif 條件式3 :
分支區塊3]
....
[else :
分支敘述]
中括號表示 elif 與 else 是可有可無的, 只有 if 時為單一分支; 只有 if 與 else為雙分支; 含有 if, 一個以上 elif, 以及 else 為多分支. Python 沒有 switch case 這種多分支指令, 只能使用 if elif else 指令來寫. 條件式會傳回 True 或 False, 可以是邏輯或比較運算式, 注意, 這些條件式在邏輯上必須是互斥 (exclusive), 否則必須將優先項目放在前面.
程式會由上而下依序判斷 if 與 elif 中的條件式, 當條件式為真時即執行縮排之分支區塊, 如果 if 與 elif 的條件式全部都不滿足才會執行 else 的分支區塊. 如果分支區塊裡面只有一個敘述, 可以直接寫在 if/elif/else 後面, 不須跳行縮排, 例如下面判斷成績等級的範例 :
score=int(input('請輸入成績:'))
if score >= 90 : print('優等')
elif score >= 80 : print('甲等')
elif score >= 70 : print('乙等')
elif score >= 60 : print('丙等')
else : print('丁等')
下列範例為金融商管應用上, 將景氣信號綜合分數轉換成景氣對策燈號 :
score=int(input('請輸入景氣對策信號綜合分數:'))
if score >= 38 : print('紅燈')
elif score >= 32 : print('黃紅燈')
elif score >= 23 : print('綠燈')
elif score >= 17 : print('黃藍燈')
else : print('藍燈')
這兩個範例的條件式並沒有互斥, 但把分數高的放在前面優先判斷 (若使用小於則分數高的要放後面), 所以結果仍然正確.
結構化程式設計主要包括下列三種語法結構 :
- 循序 (sequential)
- 分支 (branch)
- 反覆 (repeat)
1. 分支 (branch) :
分支使用條件式控制程式的執行方向, 語法如下 :
if 條件式1 :
分支區塊1
[elif 條件式2 :
分支區塊2]
[elif 條件式3 :
分支區塊3]
....
[else :
分支敘述]
中括號表示 elif 與 else 是可有可無的, 只有 if 時為單一分支; 只有 if 與 else為雙分支; 含有 if, 一個以上 elif, 以及 else 為多分支. Python 沒有 switch case 這種多分支指令, 只能使用 if elif else 指令來寫. 條件式會傳回 True 或 False, 可以是邏輯或比較運算式, 注意, 這些條件式在邏輯上必須是互斥 (exclusive), 否則必須將優先項目放在前面.
程式會由上而下依序判斷 if 與 elif 中的條件式, 當條件式為真時即執行縮排之分支區塊, 如果 if 與 elif 的條件式全部都不滿足才會執行 else 的分支區塊. 如果分支區塊裡面只有一個敘述, 可以直接寫在 if/elif/else 後面, 不須跳行縮排, 例如下面判斷成績等級的範例 :
score=int(input('請輸入成績:'))
if score >= 90 : print('優等')
elif score >= 80 : print('甲等')
elif score >= 70 : print('乙等')
elif score >= 60 : print('丙等')
else : print('丁等')
下列範例為金融商管應用上, 將景氣信號綜合分數轉換成景氣對策燈號 :
score=int(input('請輸入景氣對策信號綜合分數:'))
if score >= 38 : print('紅燈')
elif score >= 32 : print('黃紅燈')
elif score >= 23 : print('綠燈')
elif score >= 17 : print('黃藍燈')
else : print('藍燈')
這兩個範例的條件式並沒有互斥, 但把分數高的放在前面優先判斷 (若使用小於則分數高的要放後面), 所以結果仍然正確.
分支條件若為數值且形成範圍也可以用範圍條件式, 例如 :
score=int(input('請輸入成績:'))
if 90 <= score <= 100 : print('優等')
if 90 <= score <= 100 : print('優等')
if 80 <= score < 90 : print('甲等')
if 70 <= score < 80 : print('乙等')
if 70 <= score < 80 : print('乙等')
if 60 <= score < 70 : print('優等')
if 0 <= score < 60 : print('丙等')
注意, <= 與 >= 運算子等號都在右邊.
Python 沒有像 Java 或 C, PHP 的條件運算式 :
條件式 ? 運算式1 : 運算式2 (當條件式為真時執行運算式1, 否則執行運算式2)
但可以用單行條件式取代 :
變數=值1 if 條件式 else 值2
當條件式為真時變數=值1; 否則變數=值2, 例如 :
result="pass" if score >= 60 else "fail"
但這與 Java 的條件運算式仍有差異, 即限制在同一變數之取值.
2. 迴圈 (loop) :
迴圈用來處理需重複執行的迭代工作 (iteration), 可減少程式的複雜度, 在語法上又稱為反覆結構, 主要由迴圈條件 (condition) 與迴圈主體 (即要重複執行之程式碼段) 構成. 迴圈條件用來控制迴圈結束之時機, 若設定不當將使程式進入無窮迴圈狀態.
Python 的迴圈指令有兩種 :
- for 迴圈 : 進入迴圈前迴圈次數已確定
- while 迴圈 : 進入迴圈前迴圈次數不確定
(1). for 迴圈 :
for 迴圈用在進入迴圈前迴圈次數已確定之場合, 其語法如下 :
for 迭代變數 in 迭代器 :
迴圈主體
[else :
跳出執行運算式]
注意, else 區塊可有可無, 用途是在完成迴圈時執行特定工作 (但以 break 跳出迴圈時不會執行 else 內之區塊), 參考 :
# https://www.w3schools.com/python/python_for_loops.asp
下列容器都可以做為迭代器 :
- 字串 (string) : 迭代變數值為字串中的字元
- 元組 (tuple) : 迭代變數值為元素
- 串列 (list) : 迭代變數值為元素
- 字典 (dict) : 迭代變數值為鍵 (key)
- range() 函數 : 迭代變數值為 range 物件之內容
內建函數 range() 可以有 1 ~ 3 個參數 :
range() 函數 | 說明 |
range(end) | 傳回起始值 0 至 end-1 之可迭代 range 物件 |
range(start, end) | 傳回起始值 start 至 end-1 之可迭代 range 物件 |
range(start, end, step) | 傳回起始值 0 至 end-1, 步階 step 之可迭代 range 物件 |
例如下列範例為利用迴圈計算正整數數列 1, 2, 3, ... 100 之和 :
sum=0
for i in range(1, 101) : #range() 傳回內容為 1~100 整數之可迭代 range 物件
sum += i
else :
print("1~%d 正整數數列和=%d" % (100, sum)) #結果為 5050
此例用 range(1, 101) 傳回的 [1, 2, 3, ... 100] 整數串列作為迭代器來累加等差數列, 並在跳出迴圈時輸出級數和結果.
下面範例為求兩個整數 268 與 580 的公因數, 公因數必定是介於 1 與較小的數之間, 因此只要用迴圈檢查 1 與 268 之間可同時整除 268 與 580 者即為兩者之公因數 :
for i in range(1, 268):
if 268 % i == 0 and 580 % i == 0:
print(i)
此處用餘數運算子 % 檢查餘數是否為 0 (表示整除), 結果為 1, 2, 4 三數.
注意, 迭代器為字典時迭代變數為字典的鍵 (不是值), 例如 :
fruits={'蘋果':'apple','西瓜':'watermelon','香蕉':'banana'}
for fruit in fruits :
print('%s : %s' % (fruit, fruits[fruit]))
此例迭代變數 fruit 為字典變數 fruits 之鍵, 輸出結果為 :
蘋果 : apple
西瓜 : watermelon
香蕉 : banana
兩層以上迴圈稱為巢狀迴圈 (nesting loop), 需注意內外層迭代變數之不同, 例如用雙層迴圈列印九九乘法表 :
for i in range(1,10):
for j in range(1,10):
print('%d*%d=%2d' %(i, j, i*j), end=' ') #end 為一空格
print('\n') #跳行
此程式外層迭代變數為 i, 內層迭代變數為 j, 內建函數 range(1,10) 會傳回 1~9 的整數串列作為迭代器, 利用 print() 函數控制列印格式, 結果如下 :
1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 1*7= 7 1*8= 8 1*9= 9
2*1= 2 2*2= 4 2*3= 6 2*4= 8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*1= 3 3*2= 6 3*3= 9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*1= 4 4*2= 8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*1= 5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*1= 6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54
7*1= 7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63
8*1= 8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72
9*1= 9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
(2). while 迴圈 :
while 迴圈用在進入迴圈前迴圈次數已確定之場合, 其語法如下 :
while (條件式) :
迴圈主體
[else:
跳出執行運算式]
在條件式為真時會反覆執行迴圈主體中的程式碼區塊, 否則跳出迴圈, 跳出時執行 else 區塊 (但以 break 跳出迴圈不會執行 else 內之區塊). 注意, 迴圈主體中應進行條件變更, 避免成為無窮迴圈, 例如 :
i=0
while (i<6) :
print(i)
i=i+1
此程式變數 i 有一個初始值 0, 進入迴圈時先用條件式 i< 6 判斷真假, 為真才執行迴圈主體內之敘述, 迴圈內對 i 增量進行條件變更, 重複執行迴圈值到條件式為假時跳出迴圈.
(3). 迴圈中斷指令 break 與 continue :
不論是 for 或 while 迴圈, 在迴圈內部還可以在滿足特定條件式時利用 break 或 continue 指令來中斷迴圈, 不過 break 與 continue 中斷的作用不同, 執行 break 指令會跳出迴圈; 而執行 continue 指令則停止目前迴圈, 忽略後面到迴圈結尾的指令, 回到迴圈開始的地方直接進入下一個迴圈.
fruits={'蘋果':'apple','西瓜':'watermelon','香蕉':'banana'}
for fruit in fruits :
print('%s : %s' % (fruit, fruits[fruit]))
此例迭代變數 fruit 為字典變數 fruits 之鍵, 輸出結果為 :
蘋果 : apple
西瓜 : watermelon
香蕉 : banana
兩層以上迴圈稱為巢狀迴圈 (nesting loop), 需注意內外層迭代變數之不同, 例如用雙層迴圈列印九九乘法表 :
for i in range(1,10):
for j in range(1,10):
print('%d*%d=%2d' %(i, j, i*j), end=' ') #end 為一空格
print('\n') #跳行
此程式外層迭代變數為 i, 內層迭代變數為 j, 內建函數 range(1,10) 會傳回 1~9 的整數串列作為迭代器, 利用 print() 函數控制列印格式, 結果如下 :
1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 1*7= 7 1*8= 8 1*9= 9
2*1= 2 2*2= 4 2*3= 6 2*4= 8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*1= 3 3*2= 6 3*3= 9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
4*1= 4 4*2= 8 4*3=12 4*4=16 4*5=20 4*6=24 4*7=28 4*8=32 4*9=36
5*1= 5 5*2=10 5*3=15 5*4=20 5*5=25 5*6=30 5*7=35 5*8=40 5*9=45
6*1= 6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 6*7=42 6*8=48 6*9=54
7*1= 7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 7*8=56 7*9=63
8*1= 8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 8*9=72
9*1= 9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
(2). while 迴圈 :
while 迴圈用在進入迴圈前迴圈次數已確定之場合, 其語法如下 :
while (條件式) :
迴圈主體
[else:
跳出執行運算式]
在條件式為真時會反覆執行迴圈主體中的程式碼區塊, 否則跳出迴圈, 跳出時執行 else 區塊 (但以 break 跳出迴圈不會執行 else 內之區塊). 注意, 迴圈主體中應進行條件變更, 避免成為無窮迴圈, 例如 :
i=0
while (i<6) :
print(i)
i=i+1
此程式變數 i 有一個初始值 0, 進入迴圈時先用條件式 i< 6 判斷真假, 為真才執行迴圈主體內之敘述, 迴圈內對 i 增量進行條件變更, 重複執行迴圈值到條件式為假時跳出迴圈.
(3). 迴圈中斷指令 break 與 continue :
不論是 for 或 while 迴圈, 在迴圈內部還可以在滿足特定條件式時利用 break 或 continue 指令來中斷迴圈, 不過 break 與 continue 中斷的作用不同, 執行 break 指令會跳出迴圈; 而執行 continue 指令則停止目前迴圈, 忽略後面到迴圈結尾的指令, 回到迴圈開始的地方直接進入下一個迴圈.
例如計算 1~100 間的奇數和 s=1+3+5+7+....+99 可在迴圈中用 continue 跳過偶數 :
s=0
for i in range(1, 101): # 迭代 1~100 的迴圈
if i % 2 == 0: # 跳過偶數 (可被 2 整除)
continue
s += i
print(s) # 輸出 2500
此例在 i 可被 2 整除時執行 continue 直接進入下一個迭代迴圈, 這樣就把偶數跳過去不累加. 若將條件式改為 if i % 2 != 0 則是跳過奇數, 變成累加偶數 s=2+4+6+8+....+100, 結果為 2550.
此例在 i 可被 2 整除時執行 continue 直接進入下一個迭代迴圈, 這樣就把偶數跳過去不累加. 若將條件式改為 if i % 2 != 0 則是跳過奇數, 變成累加偶數 s=2+4+6+8+....+100, 結果為 2550.
不過在 "Effective Python" 這本書裡, 作者建議在 for 或 while 迴圈中最好不要使用 else 區塊, 因為其語意容易與 if else 或 try except else 中的 else 混淆而使程式解讀或維護造成困擾.
(4). 無窮迴圈 :
無窮迴圈會持續不斷執行迴圈內的敘述, 直到使用者按下 CTRL+C 強制中斷程序為止, 除非必要, 否則使用迴圈時應避免使其成為無窮迴圈.
Python 的無窮迴圈可用 for 或 while 迴圈 :
while (true) :
敘述
(1). while 無窮迴圈 :
迴圈條件式之值永遠為真的迴圈稱為無窮迴圈, 此種程序不會停止, 只能透過 CTRL+C 強制終止程序. 下面為參考 "Creative Coding in Python" 一書中的猜數字範例修改而來 :
secret_number=87
n=int(input('輸入 1~100 的數字:'))
while not (n==secret_number):
if n > secret_number:
print('您猜的數字太大了!')
else:
print('您猜的數字太小了!')
n=int(input('再輸入 1~100 的數字:'))
print('您猜對了')
下面範例綜合使用分支與迴圈來檢查身分證字號是否正確, 台灣身分證共 10 個字元, 格式如下 (例如 A123456789) :
第一個字元為英文字母, 代表出生地, 其他 9 個字元均為數字, 第一個數字 N1 代表性別, 1 表示男性, 2 表示女性, 其餘 8 個 N2~N9 是身分證號碼, 檢查身分證正確性的演算法是先將英文字母依據下列對應表轉成10~35 的數值 (出生地為舊行政區劃) :
驗證身分證字號的演算法是將英文字母對應數值 (X1X2) 的個位數 X2 乘以 9 加上十位數 X1, 然後將其餘數字由左到右分別乘以 8, 7, 6, 5, ...., 1, 1, 然後全部加總起來 :
S=X1 + X2*9 + N1*8 + N2*7 + N3*6 + N4*5 + N5*4 + N6*3 + N7*2 + N8*1 + N9
此總和若能被 10 整除即為合法之身分證字號, 程式如下 :
id=input('請輸入身分證字號:')
id=id.upper() #轉成大寫
x1x2={'A':'10','B':'11','C':'12','D':'13','E':'14','F':'15','G':'16',
'H':'17','I':'34','J':'18','K':'19','L':'20','M':'21','N':'22','O':'35',
'P':'23','Q':'24','R':'25','S':'26','T':'27','U':'28','V':'29','W':'32',
'X':'30','Y':'31','Z':'33'} #英文字母數值對應表
N=len(id) #身分證字號長度
correct_format=(N==10) and (id[0].isalpha()) and (id[1:N].isdigit())
if correct_format: #格式正確才進行驗證
acode=x1x2.get(id[0]) #取得英文字母代碼
x1=int(acode[0]) #取得字母代碼十位數
x2=int(acode[1]) #取得字母代碼個位數
i=1 #id[] 數字索引起始值 id[0] 為字母
sum=0 #總和初始值=0
for n in range(8, 0, -1): #迭代 n=8,7,6,5,4,3,2,1
sum=sum + int(id[i])* n #計算 N1 到 N8 加權之和
i += 1 #索引增量
sum=x1 + x2*9 + sum + int(id[i]) #驗證碼總和 (末項為 N9)
print("總和=", sum)
remainder=sum % 10
if remainder==0:
print("身分證字號正確")
else:
print("身分證字號不正確")
else:
print("身分證字號格式 : 1個英文字母+9個阿拉伯數字")
執行結果如下 :
請輸入身分證字號:a123456789
總和= 130
身分證字號正確
請輸入身分證字號:s121905222
總和= 152
身分證字號不正確
參考 :
# python 程式設計50題測試範例-15
# 檢查台灣身份證號碼
(4). 無窮迴圈 :
無窮迴圈會持續不斷執行迴圈內的敘述, 直到使用者按下 CTRL+C 強制中斷程序為止, 除非必要, 否則使用迴圈時應避免使其成為無窮迴圈.
Python 的無窮迴圈可用 for 或 while 迴圈 :
while (true) :
敘述
(1). while 無窮迴圈 :
迴圈條件式之值永遠為真的迴圈稱為無窮迴圈, 此種程序不會停止, 只能透過 CTRL+C 強制終止程序. 下面為參考 "Creative Coding in Python" 一書中的猜數字範例修改而來 :
secret_number=87
n=int(input('輸入 1~100 的數字:'))
while not (n==secret_number):
if n > secret_number:
print('您猜的數字太大了!')
else:
print('您猜的數字太小了!')
n=int(input('再輸入 1~100 的數字:'))
print('您猜對了')
下面範例綜合使用分支與迴圈來檢查身分證字號是否正確, 台灣身分證共 10 個字元, 格式如下 (例如 A123456789) :
英文字母 | N1 | N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 |
第一個字元為英文字母, 代表出生地, 其他 9 個字元均為數字, 第一個數字 N1 代表性別, 1 表示男性, 2 表示女性, 其餘 8 個 N2~N9 是身分證號碼, 檢查身分證正確性的演算法是先將英文字母依據下列對應表轉成10~35 的數值 (出生地為舊行政區劃) :
字母 | 數值 (X1X2) | 出生地 |
A | 10 | 台北市 |
B | 11 | 台中市 |
C | 12 | 基隆市 |
D | 13 | 台南市 |
E | 14 | 高雄市 |
F | 15 | 台北縣 |
G | 16 | 宜蘭縣 |
H | 17 | 桃園縣 |
I | 34 | 嘉義市 |
J | 18 | 新竹縣 |
K | 19 | 苗栗縣 |
L | 20 | 台中市 |
M | 21 | 南投縣 |
N | 22 | 彰化縣 |
O | 35 | 新竹市 |
P | 23 | 雲林縣 |
Q | 24 | 嘉義縣 |
R | 25 | 台南縣 |
S | 26 | 高雄縣 |
T | 27 | 屏東縣 |
U | 28 | 花蓮縣 |
V | 29 | 台東縣 |
W | 32 | 金門縣 |
X | 30 | 澎湖縣 |
Y | 31 | 陽明山 |
Z | 33 | 連江縣 |
驗證身分證字號的演算法是將英文字母對應數值 (X1X2) 的個位數 X2 乘以 9 加上十位數 X1, 然後將其餘數字由左到右分別乘以 8, 7, 6, 5, ...., 1, 1, 然後全部加總起來 :
S=X1 + X2*9 + N1*8 + N2*7 + N3*6 + N4*5 + N5*4 + N6*3 + N7*2 + N8*1 + N9
此總和若能被 10 整除即為合法之身分證字號, 程式如下 :
id=input('請輸入身分證字號:')
id=id.upper() #轉成大寫
x1x2={'A':'10','B':'11','C':'12','D':'13','E':'14','F':'15','G':'16',
'H':'17','I':'34','J':'18','K':'19','L':'20','M':'21','N':'22','O':'35',
'P':'23','Q':'24','R':'25','S':'26','T':'27','U':'28','V':'29','W':'32',
'X':'30','Y':'31','Z':'33'} #英文字母數值對應表
N=len(id) #身分證字號長度
correct_format=(N==10) and (id[0].isalpha()) and (id[1:N].isdigit())
if correct_format: #格式正確才進行驗證
acode=x1x2.get(id[0]) #取得英文字母代碼
x1=int(acode[0]) #取得字母代碼十位數
x2=int(acode[1]) #取得字母代碼個位數
i=1 #id[] 數字索引起始值 id[0] 為字母
sum=0 #總和初始值=0
for n in range(8, 0, -1): #迭代 n=8,7,6,5,4,3,2,1
sum=sum + int(id[i])* n #計算 N1 到 N8 加權之和
i += 1 #索引增量
sum=x1 + x2*9 + sum + int(id[i]) #驗證碼總和 (末項為 N9)
print("總和=", sum)
remainder=sum % 10
if remainder==0:
print("身分證字號正確")
else:
print("身分證字號不正確")
else:
print("身分證字號格式 : 1個英文字母+9個阿拉伯數字")
執行結果如下 :
請輸入身分證字號:a123456789
總和= 130
身分證字號正確
請輸入身分證字號:s121905222
總和= 152
身分證字號不正確
參考 :
# python 程式設計50題測試範例-15
# 檢查台灣身份證號碼
沒有留言:
張貼留言