前言
程序有三大結(jié)構(gòu):順序、循環(huán)和選擇。貌似有數(shù)學(xué)家給出了證明,任何一件復(fù)雜的事都是由這三種結(jié)構(gòu)組成的。
拿我們的人生舉例,每個人都要經(jīng)歷從出生到死亡的順序結(jié)構(gòu),在短暫的生命里總是會重復(fù)(循環(huán))做同一件事,上學(xué)、工作等等,同時我們也面臨著許多選擇,每一個選擇或多或少決定著人生的走向。
從這點(diǎn)來說的話,程序甚至可以模擬人生。
言歸正傳,今天給大家介紹一下新的結(jié)構(gòu)——選擇結(jié)構(gòu)。

1. 簡單示例
首先呢,我們來一起見識一下 Python 中選擇結(jié)構(gòu)大體是怎么肥事。
下面是一個簡單的示例,演示了如何使用 if 語句來正確地處理特殊情況。
假設(shè)你班 韓雷雷 同學(xué)因?yàn)樯?dǎo)致班主任點(diǎn)名的時候沒有喊'到'。
students = ['李春梅', '張翠花', '李狗蛋', '韓雷雷', '孔小乙']
for student in students:
if student == '韓雷雷':
print('班主任:', '韓雷雷', '無人回應(yīng)')
else:
print('班主任:', student + ';', student + ':', '到')
這個示例中的循環(huán)首先檢查當(dāng)前學(xué)生是不是 韓雷雷。如果是,就打印 無人回應(yīng);否則就打印 到。
結(jié)果如圖1-1:

下面正式進(jìn)入今天的主題。
2. 布爾表達(dá)式
要想看懂并學(xué)會 if 語句,不會布爾表達(dá)式可不行。
2.1 什么是布爾表達(dá)式?
布爾表達(dá)式(Boolean expression)是一段代碼聲明,它最終只有true(真)和false(假)兩個取值。最簡單的布爾表達(dá)式是等式(equality),這種布爾表達(dá)式用來測試一個值是否與另一個值相同。—— 百度百科
想想還是引用下正式的解釋比較高大上。
解釋環(huán)節(jié):
布爾表達(dá)式是一段代碼聲明,有人可能對 一段代碼聲明 有點(diǎn)犯暈,簡單地理解成一段代碼就行。
不管布爾表達(dá)式或長或短或簡單或復(fù)雜,運(yùn)行結(jié)果只有 true(真) 和 false(假) 兩個取值。
為什么說布爾表達(dá)式對 if 條件選擇語句這么重要呢?因?yàn)樯厦嫖覀兣e的點(diǎn)名例子中 if 語句后面跟著的 student == '韓雷雷' 就是布爾表達(dá)式,很巧地是這個表達(dá)式也是百度百科定義中提到地最簡單的布爾表達(dá)式——等式。

2.2 檢查是否相等
我們從最簡單的布爾表達(dá)式開始,前面提到,最簡單的布爾表達(dá)式是等式,因?yàn)?=(等號) 已經(jīng)被用來作賦值運(yùn)算符,所以判斷是否相等的等式運(yùn)算符我們用 ==(兩個等號)。
>>> name = 'Kelvin'
>>> name == 'Kelvin'
True
我們首先使用一個等號將 name 的值設(shè)置為 'Kelvin',這種做法你應(yīng)該見過很多次了。
接下來,使用兩個等號檢查 name 的值是否為 'Kelvin'。這個相等運(yùn)算符在它左右兩邊的值相等時返回 True,否則返回 False, 順便提一句, Python 里真假分別是 True/False,在其他語言里有的用的是全小寫,這個要注意。
在這個示例中,== 兩邊的值相等,因此 Python 返回 True。
如果變量 name 的值不是 'Kelvin', 上述測試將返回 False:
>>> name = 'Vicky'
>>> name == 'Kelvin'
False
一個等號是陳述,對于第一行代碼,可解讀為 將變量 name 的值設(shè)置為 'Vicky'。
兩個等號是發(fā)問,對于第二行代碼,可解讀為 變量 name 的值是 'Kelvin' 嗎?。
2.3 檢查是否不相等
要判斷兩個值是否不相等,可結(jié)合使用驚嘆號和等號(!=),其中的驚嘆號表示 非,在很多編程語言中都是如此。
假設(shè)韓雷雷身體康復(fù)回到了班級,下課時間,班上同學(xué)哈哈啊哈的聊天,只有 孔小乙 同學(xué)在認(rèn)真學(xué)習(xí)。也就是說,除了 孔小乙 同學(xué),別的同學(xué)都在哈哈哈。
我們用代碼記錄了這一刻:
students = ['李春梅', '張翠花', '李狗蛋', '韓雷雷', '孔小乙']
for student in students:
if student != '孔小乙':
print(student + ': ', '哈哈啊哈')
循環(huán)班級同學(xué)的名字,如果不是 孔小乙 就 哈哈啊哈。
運(yùn)行這段代碼,結(jié)果如圖2-1:

可以看到課間就只有 孔小乙 同學(xué)仍在好好學(xué)習(xí)天天向上。
2.4 比較數(shù)字
檢查數(shù)值非常簡單,例如,檢查 李狗蛋 同學(xué)的數(shù)學(xué)成績:
>>> grade = 60
>>> grade == 60
True
李狗蛋 同學(xué)的成績剛好60分,所以返回 True。
除此之外還能進(jìn)行不相等的檢查,例如判斷 李狗蛋 的成績不等于90分:
>>> grade = 60
>>> grade != 90
True
因?yàn)?狗蛋 的成績確實(shí)不等于90分,所以返回的還是 True,非常符合邏輯。
學(xué)數(shù)學(xué)的時候我們除了可以比較兩個數(shù)字等于或不等,還可以判斷是不是大于、小于、大于等于和小于等于。Python 肥腸貼心地給我們提供了這些判斷符號。
>>> grade = 60
>>> grade < 60
False
>>> grade <= 60
True
>>> grade > 60
False
>>> grade >= 60
True
這些比較符的運(yùn)用和我們數(shù)學(xué)上的含義是一樣的。
2.5 檢查多個條件
你可能想同時檢查多個條件,例如,有時候你需要在兩個條件都為 True 時才執(zhí)行相應(yīng)的操作,而有時候你只要求一個條件為 True 時就執(zhí)行相應(yīng)的操作。
由此引入了關(guān)鍵字 and 和 or。
2.5.1 關(guān)鍵字 and
如果你熟悉邏輯運(yùn)算的概念,那么 and 指的是邏輯與運(yùn)算。
不熟悉也沒有關(guān)系,以兩個條件為例,我粗略地做了張表:
| p | q | p and q |
|---|---|---|
| True | True | True |
| True | False | False |
| False | True | False |
| False | False | False |
and 關(guān)鍵字的特點(diǎn)是:只有左右兩邊條件都為 True 時,結(jié)果才為 True,否則都是 False。
例如,要檢查兩個同學(xué)的年齡是否都不小于 16 歲,代碼如下:
>>> age_0 = 18
>>> age_1 = 14
>>> age_0 >= 16 and age_1 >= 16
False
>>> age_1 = 20
>>> age_0 >= 16 and age_1 >= 16
True
我們先定義了兩個變量 age_0 和 age_1 來存儲年齡。
age_0 >= 16 and age_1 >= 16 這種寫法其實(shí)和 (age_0 >= 16) and (age_1 >= 16) 等價的。先判斷 age_0 >= 16,因?yàn)?age_0 的值是18,所以滿足條件,返回的是True,然后判斷age_1 >= 16,因?yàn)?code>age_1 的值是14,所以不滿足條件,返回的是 False,最后and 運(yùn)算符左邊的是 True,右邊的是 False,類似這樣 True and False,根據(jù)and 關(guān)系表格可知,結(jié)果是 False。
然后我們修改了第二個學(xué)生的年齡:age_1 = 20,再次進(jìn)行 and 運(yùn)算時,由于age_1 的值現(xiàn)在是20,所以滿足條件,返回的也是 True,類似這樣 True and True,根據(jù) and 關(guān)系表格可知,結(jié)果是 True。
因此 and 運(yùn)算也可以總結(jié)為:只要有一個條件不滿足,整個布爾表達(dá)式就為 False。
2.5.2 關(guān)鍵字 or
如果你熟悉邏輯運(yùn)算概念,那么 or 指的是邏輯或運(yùn)算。
同樣地,不熟悉也沒關(guān)系,以兩個條件為例,我粗略地做了張表:
| p | q | p or q |
|---|---|---|
| True | True | True |
| True | False | True |
| False | True | True |
| False | False | False |
or 關(guān)鍵字的特點(diǎn)是:只有左右兩個條件都為 False時,結(jié)果才為 False,否則都是 True
下面再次檢查兩位同學(xué)的年齡,條件是至少有一個人的年齡不小于16歲,代碼如下:
>>> age_0 = 18
>>> age_1 = 14
>>> age_0 >= 16 or age_1 >= 16
True
>>> age_0 = 15
>>> age_0 >= 16 or age_1 >= 16
False
我們先定義了兩個變量 age_0 和 age_1 來存儲年齡。
age_0 >= 16 or age_1 >= 16 這種寫法其實(shí)和 (age_0 >= 16) or (age_1 >= 16) 等價的。先判斷 age_0 >= 16,因?yàn)?age_0 的值是18,所以滿足條件,返回的是True,然后判斷age_1 >= 16,因?yàn)?code>age_1 的值是14,所以不滿足條件,返回的是 False,最后and 運(yùn)算符左邊的是 True,右邊的是 False,類似這樣 True or False,根據(jù)or 關(guān)系表格可知,結(jié)果是 True。
然后我們修改了第一個學(xué)生的年齡:age_0 = 15,再次進(jìn)行 or 運(yùn)算時,由于age_0 的值現(xiàn)在是15,所以不滿足條件,返回的也是 False,類似這樣 False or False,根據(jù) or 關(guān)系表格可知,結(jié)果是 False。
因此 or 運(yùn)算也可以總結(jié)為:只要有一個條件滿足,整個布爾表達(dá)式就為 True。
2.6 檢查特定值是否包含在列表中
有時候,執(zhí)行操作前必須檢查列表是否包含特定的值。
要判斷特定的值是否已包含在列表中,可使用關(guān)鍵字 in。
下面代碼,將檢查 馬冬梅 和 韓雷雷 是否包含在學(xué)生列表中:
>>> students = ['李春梅', '張翠花', '李狗蛋', '韓雷雷', '孔小乙']
>>> '馬冬梅' in students
False
>>> '韓雷雷' in students
True
這個關(guān)鍵字很有用,可以輕松地檢查列表中是否包含特定的值。
2.7 檢查特定值是否不包含在列表中
還有的時候,需要確定特定的值未包含在列表中。
在這種情況下,可使用關(guān)鍵字 not in。
下面代碼,將檢查 馬冬梅 和 韓雷雷 是否不包含在學(xué)生列表中:
>>> students = ['李春梅', '張翠花', '李狗蛋', '韓雷雷', '孔小乙']
>>> '馬冬梅' not in students
True
>>> '韓雷雷' not in students
False
可以看到,馬冬梅 確實(shí)不包含在學(xué)生列表中,所以返回的是 True,而 韓雷雷 包含在學(xué)生列表中,我們判斷條件是不包含,所以返回的是 False。
能堅持看到這里說明你對學(xué)習(xí) Python 具有了起碼的意志力,這些符號或許剛開始會讓你眼花繚亂,更甚至你連邏輯運(yùn)算也沒有聽說過。當(dāng)你有這種感覺時,聽我一句,實(shí)打?qū)嵉卦陔娔X上敲下這些代碼,看看運(yùn)行之后的效果,有些東西,你就不知不覺地掌握了。
3. if 語句
理解布爾表達(dá)式以后,就可以開始編寫 if 語句了。
if 語句有很多種,選擇使用哪種取決于要測試的條件數(shù)。
3.1 簡單的 if 語句
本來想在這小節(jié)標(biāo)題上加個最簡單,后來想想,話說太滿容易被杠就劃掉了。
最簡單的 if 語句只有一個簡單的布爾表達(dá)式和一個操作:
if conditional_test:
do something
如果conditional_test 的結(jié)果為True,Python 就會執(zhí)行緊跟在 if 語句后面的代碼;否則 Python 將忽略這些代碼。
假設(shè)知道了某人的年齡,需要你判斷這個人是否有選舉投票權(quán):
age = 19
if age >= 18:
print("你已經(jīng)有資格參與選舉投票啦!")
age >= 18 是個布爾表達(dá)式,判斷 age 是否不小于18歲,age 的值是19,矮擺滿足條件,因此 Python 執(zhí)行縮進(jìn)的 print 語句。
運(yùn)行這段代碼,結(jié)果如3-1:

在 if 語句中,縮進(jìn)的作用與for循環(huán)中相同。如果測試通過了,將執(zhí)行 if 語句后面所有縮進(jìn)的代碼,否則將忽略它們。
在緊跟 if 語句后面的代碼塊中,可根據(jù)需要包含任意數(shù)量的代碼行。
就拿剛剛判斷某人年齡達(dá)不達(dá)到選舉資格的例子:
age = 19
if age >= 18:
print("你已經(jīng)有資格參與選舉投票啦!")
print("啦啦啦~你是祖國的小紅花~")
if 后面的布爾表達(dá)式為真,并且兩條 print 語句都縮進(jìn)了,因此他們都被執(zhí)行了,效果如圖3-2:

如果 age 的值小于18,這個程序?qū)⒉粫腥魏屋敵觥?/p>
3.2 if-else 語句
經(jīng)常需要在布爾表達(dá)式為真時執(zhí)行一系列操作,并在表達(dá)式為假時執(zhí)行另一系列操作。
在這種情況下,可使用 Python 提供的 if-else 語句。
if-else 語句塊類似于簡單的 if 語句,但其中的 else 語句讓你能夠在表達(dá)式為假時執(zhí)行一些操作。
假如,已知某人年齡,在其滿足投票年齡時打印一些信息,若其不夠投票年齡,也顯示一條信息:
age = 17
if age >= 18:
print("你已經(jīng)有資格參與選舉投票啦!")
print("啦啦啦~你是祖國的小紅花~")
else:
print("對不起,您太年輕了還不能參與投票")
print("未滿18還是一枝花~")
如果 age >= 18 返回的是 True,就執(zhí)行第一個縮進(jìn)的代碼塊;如果返回的是 False,就執(zhí)行 else 代碼塊。
這次 age 的值是17,布爾表達(dá)式返回是 False,因此執(zhí)行 else 代碼塊中的代碼。
結(jié)果如圖3-3:

上述代碼之所以可行,是因?yàn)橹淮嬖趦煞N情形:要么夠投票年齡,要么不夠。
if-else 非常適合用于要讓 Python 執(zhí)行兩種操作之一的情形。
因?yàn)榉谴思幢?,總是會?zhí)行兩個操作中的一個。
辣么,如果存在三種及以上的選擇情況咋辦?下面介紹最復(fù)雜的 if 語句結(jié)構(gòu)。
3.3 if-elif-else 語句
Python 只執(zhí)行 if-elif-else 結(jié)構(gòu)中的一個代碼塊,它依次檢查每個表達(dá)式,直到遇到返回值為真的表達(dá)式,然后 Python 將執(zhí)行緊跟在它后面的代碼,并跳過余下的代碼塊。
例如,來看個景點(diǎn)收費(fèi)的標(biāo)準(zhǔn):
4歲以下免費(fèi);
4~18歲收費(fèi)30元;
18歲(含)以上收費(fèi)60元。
如果只使用一條 if 語句,我們貌似也可以確定景點(diǎn)票價:
age = 12
if age < 4:
print("您可以免費(fèi)進(jìn)入景點(diǎn)")
if (age >= 4) and (age < 18):
print("您的票價是 30 元")
if age >= 18:
print("您的票價是 60 元")
我們先給 age 賦值為12;
然后 age 先和4進(jìn)行比較,發(fā)現(xiàn)不滿足條件,所以不執(zhí)行 if age < 4 后面的代碼塊;
接著 age 和4、18比較,發(fā)現(xiàn)恰好同時滿足大于等于4、小于18,因此執(zhí)行 if (age >= 4) and (age < 18) 后面的代碼塊;
最后 age 和18進(jìn)行比較,發(fā)現(xiàn)不滿足條件,所以不執(zhí)行 if age >= 18 后面的代碼塊。
所以,運(yùn)行結(jié)果如圖3-4:

果然如我們分析的那樣,執(zhí)行了第二個 if 語句后面的代碼塊。
不知道你們發(fā)現(xiàn)沒有,像上面這種寫法,不管游客年齡如何,都需要比較3次。
下面我們來看看使用 if-elif-else 結(jié)構(gòu)是如何寫的:
age = 2
if age < 4:
print("您可以免費(fèi)進(jìn)入景點(diǎn)")
elif age < 18:
print("您的票價是 30 元")
else:
print("您的票價是 60 元")
我們先給 age 賦值為2;
然后 age 先和4進(jìn)行比較,發(fā)現(xiàn)滿足條件,所以執(zhí)行了 if age < 4 后面的代碼塊;
最后,跳過余下的代碼塊。
看出區(qū)別了沒:采用 if-elif-else 寫法就比較了1次,代碼執(zhí)行效率上有了很大的提升。
當(dāng)然也不是每次都只執(zhí)行一次,就上述代碼而言,一般在1~3次之間,所以效率上對比采用 if 語句寫出的程序而言是很高的。
為了讓代碼優(yōu)雅而不失簡潔,可不在 if-elif-else 代碼塊中打印出門票價格,而只在其中設(shè)置門票價格,并在它后面添加一條簡單的 print 語句:
age = 12
if age < 4:
price = 0
elif age < 18:
price = 30
else:
price = 60
print("您的門票價格是:" + str(price) + " 元")
在 if-elif-else 代碼塊中設(shè)置門票價格,最后在一條未縮進(jìn)的 print 語句中根據(jù)設(shè)置的門票價格打印出一條消息。
這些代碼的輸出和前一個示例相同,但 if-elif-else 結(jié)構(gòu)的作用更小,它只確定門票價格,而不是在確定門票價格的同時打印一條消息。除效率更高外,這些修訂后的代碼還更容易修改:要調(diào)整輸出消息的內(nèi)容,只需要修改一條而不是三條print 語句。
3.4 使用多個 elif 代碼塊
可根據(jù)需要使用任意數(shù)量的 elif 代碼塊。
例如,前述景點(diǎn)要給老年人打折,可再添加一個判斷條件,判斷游客是否符合打折條件。假設(shè)對于65歲(含)以上的老人,可以半價(即 30 元)購買門票:
age = 75
if age < 4:
price = 0
elif age < 18:
price = 30
elif age < 65:
price = 60
else:
price = 30
print("您的門票價格是:" + str(price) + " 元")
代碼大體沒變。第二個 elif 代碼塊通過檢查確定年齡不到65歲后,才將票價設(shè)為最高票價(60 元)。當(dāng)我們將年齡設(shè)為75時,程序會進(jìn)入到 else 代碼塊并執(zhí)行其中的代碼。
結(jié)果你們也猜到了,猜不到的看圖3-5:

3.5 省略 else 代碼塊
Python 并不要求 if-elif 結(jié)構(gòu)后面一定要有 else 代碼塊。
在有些情況下,else 代碼塊很有用;而有些情況,去掉 else 語句意思表達(dá)的或許更清晰。
繼續(xù)拿景點(diǎn)門票舉例:
age = 75
if age < 4:
price = 0
elif age < 18:
price = 30
elif age < 65:
price = 60
elif age >= 65:
price = 30
print("您的門票價格是:" + str(price) + " 元")
最后一個 elif 代碼塊在游客年齡超過65(含)時,將價格設(shè)置為30元,這比我們使用 else 代碼塊更清晰些。
else 是一條神奇的語句,只要不滿足任何 if 或 elif 中的布爾表達(dá)式,else 代碼塊中的代碼就會執(zhí)行。
結(jié)尾語
關(guān)于 if 語句還有些需要注意點(diǎn),比如,變量為 None 怎么判斷,if 語句的書寫格式等等。但這些展開說的話篇幅就太長了,且不是重點(diǎn),所以就省略啦(主要是怕你們看睡著)。
如果有誰精力旺盛想看的話,可以關(guān)注下面↓↓↓的微信公眾號給我留言,或者有啥問題我們也可以相互討論學(xué)習(xí)、共同進(jìn)步。
最后,祝你學(xué)有所成。
