在程式語言中,我們經常需要做條件判斷,
「如果...就做...」,
if-else在程式碼中出現的比率應該算是相當高的,
然而在python中的if-else怎麼寫是很有學問的,
過於多層的if-else嵌套,
容易使程式邏輯複輯,難以除錯
這一篇從語法及邏輯出發,教大家如何避免寫出冗長的if-else
技巧1- 布林值本身不要再包一層if-else了
舉個簡單的例子,
例如希望寫一個函數判斷一個整數是否是偶數,
經驗不足的人可能會順手寫出以下程式:
def isEven(n):
if n%2 == 0:
return True
else:
return False
看起來是沒有什麼問題,
但其實n%2 == 0本身是一個條件判斷式,
n%2 == 0 的值已經是True或是False了,
因此這段程式可以簡單用一句話來寫:
def isEven(n):
return n%2 == 0
技巧2 – 三元運算式語法
三元運算式的語法為:
變數 = 值1 if 條件式 else 值2
如果條件式的值為True,變數就會等於值1,
否則變數等於值2。
注意使用三元運算子語法時,
if-else一定要成對出現。
例如現在我們想要判斷一個變數型態是否為整數,
我們可以用type()函數檢查一個變數的型態。
化簡前:
n = 5
T=""
if type(n)==int:
T="n是整數"
else:
T="n不是整數"
化簡後:
n = 5
T= "n是整數" if type(n)==int else "n不是整數"
這樣寫的好處不光是程式碼變短了,
還能避免撰寫重複的程式碼,
原本你的T=共寫了兩次,
化簡後T=只要寫一次,
萬一變數名稱有變動的時候,
才不會改了第一個忘記改第二個
NG範例:
if type(n)==int:
t="n是整數" # 變數t改成小寫,下面的else區塊卻忘記同步改
else:
T="n不是整數"
技巧3 – 利用in合併多個條件式
in這個關鍵字除了平時較常用的與for搭配的語法外(例如for i in range(3):),
亦可作為條件判斷,
A in B即是判斷物件A是否在容器B裡,
例如:
>>> 1 in [1,2,3]
True
>>> "a" in "apple"
True
例如現在給你一個單字,
要你判斷這個單字的字首是不是母音('a','e','i','o','u')。
化簡前:
word = "apple"
if word[0] == 'a' or word[0] == 'e' or word[0] == 'i' or word[0] == 'o' or word[0] == 'u':
print("單字開頭為母音")
五個判斷式同樣以word[0]這個字來做等式判斷,
實在太冗長了。
可以用in做改寫會簡單許多。
化簡後:
word = "apple"
if word[0] in 'aeiou':
print("單字開頭為母音")
這樣寫的好處不光是語法精簡,
同上面的道理,避免重複的程式碼word[0] ==寫很多次,
難保說複製貼上多次,
需求改變的時候,
你會不會有小地方忘記改到
NG範例(這邊改成判斷單字尾巴為母音,其中打字疏忽,word[0] == 'o'漏改為word[-1] == 'o') :
word = "apple"
if word[-1] == 'a' or word[-1] == 'e' or word[-1] == 'i' or word[0] == 'o' or word[-1] == 'u':
print("單字結尾為母音")
技巧4 – 利用列表或字典化簡大量if-elif
範例: 十二生肖
民國1年是鼠年,
想要寫一個程式判斷今年是什麼年(鼠、牛、虎、兔、…)。
化簡前:
year = int(input())
if year%12 == 1:
print("今年是鼠年")
elif year%12 == 2:
print("今年是牛年")
elif year%12 == 3:
print("今年是虎年")
# …
#省略部分程式碼
# …
elif year%12 == 11:
print("今年是狗年")
elif year%12 == 0:
print("今年是豬年")
哇,光是判斷十二生肖就寫了12個if-elif了,
其實像這類有大量if-elif,但裡面做的事相同(同樣是print一個字串),
便適合用list或dict建立對應關係
化簡後:
year = int(input())
S = ["豬","鼠","牛","虎","兔","龍","蛇","馬","羊","猴","雞","狗"]
print("今年是"+S[year%12]+"年")
改成用列表取index的方式來做,
把if-elif全部省略了,
是不是非常簡潔易讀呢?
範例: 撲克花色
假設我們想把英文字母與撲克牌的花色做轉換,
且看以下程式:
化簡前:
letter = input()
suit = ""
if letter == 's':
suit = "黑桃"
elif letter == 'h':
suit = "紅心"
elif letter == 'd':
suit = "方塊"
elif letter == 'c':
suit = "梅花"
這時便很適合用python的字典化簡它。
化簡後:
letter = input()
D = {'s':"黑桃", 'h':"紅心", 'd':"方塊", 'c':"梅花"}
suit = D[letter]
技巧5 – 化簡多重嵌套if-else
首先提一下什麼是嵌套的if-else,
簡單來說就是if區塊裡面又包了一層if,
例如以下例子,假設我們想要根據學生的分數,
印出不同的字串給序回饋:
score = int(input('請輸入你的分數: '))
if score>100 or score<0:
print('輸入的成績不合法')
elif score>60:
if 85<=score<=89:
print('你真棒,差一點就可以A+了')
elif score>=99:
print('哇塞,你是神人吧')
else:
print('恭喜你及格,不用重補修')
else:
print('好課值得一修再修,明年請再重修這門課')
這個例子只有兩層if-else,
故且還看的懂,
然而在真實專案中,偶有工程式寫到三、五層嵌套if-else,
每個if-else區塊中還有上百行程式碼,
這時讀程式碼的人就會讀的很痛苦
請避免在程式碼中寫出嵌套的if-else,
真的難以避免的話,請以兩層if-else為限,
以免超過人類適合閱讀的邏輯
<上述程式優化方案>
首先,將有嵌套邏輯的地方改包裝成函數,
def jugdeStr(score):
# 根據score 回傳適當的字串評語
if score>100 or score<0:
return '輸入的成績不合法'
elif score>60:
if 85<=score<=89:
return '你真棒,差一點就可以A+了'
elif score>=99:
return '哇塞,你是神人吧'
else:
return '恭喜你及格,不用重補修'
else:
return '好課值得一修再修,明年請再重修這門課'
score = int(input('請輸入你的分數: '))
print(jugdeStr(score))
在函數中,碰到return就會跳出函數,
因此常常可以拆解雙層if-else邏輯,
變成僅有單層的if
化簡後:
def jugdeStr(score):
# 根據score 回傳適當的字串評語
if score>100 or score<0:
return '輸入的成績不合法'
if 85<=score<=89:
return '你真棒,差一點就可以A+了'
if score>=99:
return '哇塞,你是神人吧'
if score>60:
return '恭喜你及格,不用重補修'
return '好課值得一修再修,明年請再重修這門課'
score = int(input('請輸入你的分數: '))
print(jugdeStr(score))
化簡後的函數一個else都不需要寫,
而且邏輯流程會清晰許多
經典題分享- 判斷閏年
判斷閏年可能是新手練程式常做到的一道題,
在曆法中,
若n是4的倍數但不是100的倍數,
或者n是400的倍數,
則n 為閏年。
希望實作一個函數輸入數字n,
回傳n是否為閏年
由於閏年的描述較為複雜,
經驗不足很容易就寫成嵌套邏輯,
弄的相當複雜:
def isLeapYear(n):
if n%4==0:
if n%100!=0:
return True
else:
if n%400 ==0:
return True
else:
return False
else:
return False
然而此函數其實可以寫的相當乾淨簡潔:
def isLeapYear(n):
return (n%4==0 and n%100!=0) or n%400==0
此例留給大家欣賞學習