包教包會!7段程式碼帶你玩轉Python條件語句(附程式碼)

資料派THU發表於2019-09-02

[ 導 讀 ]條件語句透過一個或多個布林表示式的執行結果(真值或假值)決定下一步的執行方向。所謂布林表示式,即對某個物件進行布林運算,產生一個bool值。條件語句的執行邏輯為:如果條件被滿足(返回真值),可以做某件事情;如果條件不滿足(返回假值),就做另一件事情,或什麼也不做。

透過圖1,可以對條件語句的執行機制作有一個簡單的瞭解。虛線框內是一個選擇結構,此結構中包含一個判斷條件和兩條執行語句,以及連線各部分的流向線。根據判斷條件(布林表示式)返回值的情況,程式將選擇執行語句1或語句2。

包教包會!7段程式碼帶你玩轉Python條件語句(附程式碼)圖1 條件語句結構

在Python中,實現選擇結構最普遍的工具是if語句。此外,try語句專門用於異常處理,其內在邏輯也符合選擇結構。

01 if、elif與else

if語句中包含3種條件判斷句式,即if、elif和else。其中,if與elif部分都包含判斷條件,當判斷條件都不成立時,程式才能執行else部分的程式碼。

if語句最基礎的形式是if-else,其基本語法格式如下。

if 條件表示式:
    操作語句1
else:
    操作語句2

if-else語句常用的引數及說明:

條件表示式:接收布林表示式,表示判斷條件是否成立。無預設值

操作語句:接收操作語句,表示執行一段程式碼。無預設值

if-else語句執行時,程式首先判斷if部分條件表示式的真假。如果條件表示式返回真值,則執行操作語句1;如果返回假值,則執行操作語句2。

if-else語句的形式很簡單,透過條件判斷的結果即可決定下一步的執行方向,具有兩條分支。以編寫一個賬戶密碼登入介面為例,介紹該語句的使用,如程式碼清單①所示。

程式碼清單① if-else語句實現登入介面

In[1]:    name = input ('請輸入使用者名稱:')
    password = input ('請輸入密碼:')
    if name == "Lucy" and password == "123456":
        print ('****登入成功,歡迎!*****')
    else:
        print ('-----您的輸入有誤,登入失敗!-----')    

Out[1]:    請輸入使用者名稱:Lucy
    請輸入密碼:123
    -----您的輸入有誤,登入失敗!-----  

In[2]:    name = input ('請輸入使用者名稱:')
    password = input ('請輸入密碼:')
    if name == "Lucy" and password == "123456":
        print ('****登入成功,歡迎!*****')
    else:
        print ('-----您的輸入有誤,登入失敗!-----')    

Out[2]:    請輸入使用者名稱:Lucy
    請輸入密碼:123456
    ****登入成功,歡迎!*****

在程式碼清單①中,使用input函式以支援互動式的輸入,並在函式括號內插入文字進行了輸入提示,增強了登入介面的人性化。在if部分的條件判斷式中,使用and運算子進行且運算,只有賬戶和密碼都輸入正確才能成功登入,從而增加了安全性。

if-else語句可以縮減為單行形式,其基本語法格式如下。

操作語句1 if 條件表示式 else 操作語句2

if-else語句單行形式語法格式中的引數說明與圖1一致。如果條件表示式返回的結果為真,則執行if前面的操作語句1,否則執行else後面的操作語句2。

if-else語句使用單行形式的目的主要在於增加程式碼的簡潔性,其基本使用方法如程式碼清單②所示。

程式碼清單② if-else語句的單行形式

In[3]:    num1, num2 = 11, 90
    print('num1加num2為百分數') if 1000 > num1 + num2 >100 else 
            print('num1加num2不為百分數') 

Out[3]:    num1加num2為百分數

if-else語句有明顯的缺陷,即只能實現兩條分支。實際工作中需要用到的條件分支數目可能難以想象,擴充套件if語句的分支需要用到elif句式。elif是“else if”的縮寫,即“下一條件是否成立?”

使用elif有簡潔、減少過分縮排的效果。將elif程式碼塊放在if和else之間,就組成了if-elif-else語句。理論上,if語句中的elif可以無限多。if-elif-else語句與if-else語句其實是等價的,後者相當於前者中elif個數為0或不執行的情況。由於if-elif-else語句能提供更多條件分支,因此被普遍使用,其基本語法格式如下。

if 條件表示式1:
    操作語句1
elif 條件表示式2:
    操作語句2
else:
    操作語句3

if-elif-else語句語法格式中的引數與上文說明一致。該語句執行時,按照從上到下的順序,依次檢查每個條件表示式返回值的情況,任何一個條件表示式返回真值,就執行該表示式下面的操作語句,若所有條件表示式都返回假值,則執行else下面的操作語句。

if-elif-else語句相對於if-else語句優勢明顯,可以實現更為複雜的功能。使用if-elif-else語句實現年齡段的判斷,如程式碼清單③所示。

程式碼清單③ 使用if-elif-else語句實現年齡段的判斷

In[4]:    age = input('請輸入您的年齡:')
    age = int(age)
    if age < 18:
        print('未成年人!')
    elif age >= 18 and age <= 25:
        print('青年人!')
    elif age > 25 and age <= 60:
        print('中年人!')
    else:
        print('老年人!')   

Out[4]:    請輸入您的年齡: 20
    青年人!

程式碼清單③透過比較運算子實現了年齡段劃分,並能區分年齡段界限,避免邏輯出錯。input函式將接收的任何資料型別都預設為str,如果不在該程式碼中插入轉換接收資料型別的語句,程式將無法執行。這是因為,接收的年齡資料會被用於和後續的年齡數值比較,而number與str是無法比較的。

需要說明,if語句還有一種形式是if-if-else,這一形式中的if可以有多個,從而實現多分支。與if-elif-else語句相比,差異不僅僅存在於形式上,效能上也同樣有區別,使用多個if的效率更低,它實際上是多重if語句。

if語句支援巢狀,即在一個if語句中嵌入另一個if語句,從而構成不同層次的選擇結構。巢狀的意義在於實現多層選擇結構。使用巢狀對條件語句的功能有昇華作用,這與elif是相似的,elif將有限的條件分支擴充套件,巢狀則提供了建立多層選擇結構的工具,兩者分別在不同的維度上提升了if語句的功能性。使用巢狀需要以不同的縮排長度劃分程式碼結構的層次,因此巢狀時要特別注意縮排的規範性。

巢狀選擇結構具有很廣的應用場景,以下給出一個例子。假設系統中儲存了5個使用者的身份資訊,分別是:來自英國的Tom,35歲;來自法國的Frank,35歲;來自德國的Bob,35歲;來自澳大利亞的Washington,51歲;來自南非的Jane,21歲。

設計一個程式,詢問使用者的部分資訊,在對方不說出自己名字的情況下識別其身份,如程式碼清單④所示。

程式碼清單④ 巢狀if-elif-else語句

In[5]:    age = input('請輸入你的年齡:')
    age = int(age)
    if age == 35:
        nation = input('請輸入你的國籍:')
        if nation == '英國':
            print('你是Tom! ')
        elif (nation == '法國'):
            print('你是Frank! ')
        else:
            print('你是Bob! ')
    elif age == 21:
       print('你是Jane,來自南非! ')
    elif age == 51:
       print('你是Washington,來自澳大利亞! ')
    else:
       print('請輸入正確年齡值! ')  

Out[5]:    請輸入你的年齡:35
    請輸入你的國籍:法國
    你是Frank!

從程式碼清單④可以看到,該程式具有兩層選擇結構。第1層用於詢問年齡,程式透過接收的年齡,可以判斷輸入者是Jane、Washington或其他3個同齡人中的一個;若收到的值不在這5人年齡範圍中,則提示輸入出錯;若收到的值是3個同齡人的歲數,則進入下一層選擇結構,即詢問國籍;透過詢問國籍,程式可以準確報出輸入者的資訊。

使用if語句時,需要注意以下幾點。

條件判斷語句應儘量簡單,若語句複雜則應當將運算先放到一個變數中。

Python的條件語句中允許常用的數值比較運算(==,!=,>,>=,<,<=)。

Python允許無限次if語句巢狀,但實際程式設計中如果必須用到3級到4級巢狀,建議考慮用其他方法編寫程式碼,巢狀超過兩層會使程式的執行效率大打折扣。包教包會!7段程式碼帶你玩轉Python條件語句(附程式碼)

2. try、except與else

如果執行途中發生錯誤事件,程式的執行將中斷,並建立異常物件。異常是程式在正常流程控制以外採取的動作,當它被引發時,計算機將自動尋找異常處理程式,以幫助程式恢復正常執行。

要保證程式的正常執行,就需要排除錯誤,錯誤要麼是語法上的,要麼是邏輯上的。語法錯誤的出現表明程式在結構上出現了問題,可以在程式執行前加以糾正。邏輯錯誤可能是缺少輸入或輸入不正確,某些情況下,也可能是根據輸入無法生成預期的結果。邏輯錯誤難以預防,必須使用異常處理程式來應對。

計算機語言針對可能出現的錯誤定義了異常型別,某種錯誤引發對應的異常時,異常處理程式將被啟動,從而恢復程式的正常執行。Python中定義的異常型別大致分為數值計算錯誤、作業系統錯誤、無效資料查詢、Unicode相關的錯誤和警告等幾類,如下所示。

Python異常類:

BaseException:所有異常的基類

Exception:常規異常的基類

StandardError:所有的內建標準異常的基類

ArithmeticError:所有數值計算異常的基類

FloatingPointError:浮點計算異常

OverflowError:數值運算超出最大限制

ZeroDivisionError:除零

AssertionError:斷言語句失敗

AttributeError:物件不包含某個屬性

EOFError:沒有內建輸入,到達EOF標記

EnvironmentError:作業系統異常的基類

IOError:輸入/輸出操作失敗

OSError:作業系統異常

WindowsError:系統呼叫失敗

ImportError:匯入模組/物件失敗

KeyboardInterrupt:使用者中斷執行

LookupError:無效資料查詢的基類

IndexError:序列中沒有此索引

KeyError:對映中沒有這個鍵

MemoryError:記憶體溢位異常

NameError:未宣告/初始化物件

UnboundLocalError:訪問未初始化的本地變數

ReferenceError:弱引用試圖訪問已經垃圾回收了的物件

RuntimeError:一般的執行時異常

NotImplementedError:尚未實現的方法

SyntaxError:語法錯誤導致的異常

IndentationError:縮排錯誤導致的異常

TabError:Tab和空格混用

SystemError:一般的直譯器系統異常

TypeError:對型別無效的操作

ValueError:傳入無效的引數

UnicodeError:Unicode相關的異常

UnicodeDecodeError:Unicode解碼時的異常

UnicodeEncodeError:Unicode編碼錯誤導致的異常

UnicodeTranslateError:Unicode轉換錯誤導致的異常

Warning:警告的基類

DeprecationWarning:關於被棄用的特徵的警告

FutureWarning:關於構造將來語義會有改變的警告

UserWarning:使用者程式碼生成的警告

PendingDeprecationWarning:關於特性將會被廢棄的警告

RuntimeWarning:可疑的執行時行為(runtime behavior)的警告

SyntaxWarning:可疑語法的警告

ImportWarning:用於在匯入模組過程中觸發的警告

UnicodeWarning:與Unicode相關的警告

BytesWarning:與位元組或位元組碼相關的警告

ResourceWarning:與資源使用相關的警告

異常體系內部有層次關係,即某些異常屬於某個異常的子類,該異常又可能是另一異常的子類。較低層次、更具細節的異常是某些異常的子類,這些高層次的異常則稱為基類,子類和基類是相對的。Python異常體系中的部分關係如圖2所示。

包教包會!7段程式碼帶你玩轉Python條件語句(附程式碼)圖2 Python常見異常體系在圖2中,越下面的異常,其層次越低,細節更明顯,它們總有更高層次的基類。

Python使用try語句處理異常,該語句一般包括try、except和else三個句式,組成try-except-else的形式。try部分包含一個嘗試執行的程式碼塊,except部分是特定異常的處理對策,else部分則在程式執行正常時執行。

try語句可以視為一種條件分支,與if語句的區別是try語句並不包含條件判斷式,執行的流向也不取決於條件表示式,而依賴於程式碼塊能否執行。但其內在邏輯和執行流程與if語句是相似的,符合條件分支的特徵,其基本語法格式如下。

try:
    操作語句1
except 錯誤型別1:
    操作語句2
except 錯誤型別2:
    操作語句3
else:
    操作語句4

try語句常用的語法格式及其引數說明如下所示。

try-except-else語句常用的語法格式及其引數說明:

錯誤型別:接收Python異常名,表示符合該異常則執行下面語句。無預設值

操作語句:接收操作語句,表示執行一段程式碼。無預設值

執行try-except-else語句時,程式首先執行try程式碼塊,即可能出錯的試探性語句,這可能導致致命性錯誤使得程式無法繼續執行。如果try程式碼塊確實無法執行,就可能執行某個except程式碼塊。

執行一個except程式碼塊的條件是,系統捕捉的異常型別和該程式碼塊標識的型別相符合;如果try程式碼塊的語句正常執行,就接著執行else程式碼塊的語句。

如果try部分無法執行,也沒有找到相應的except程式碼塊,就將異常訊息傳送給程式呼叫端,如Python Shell,Python Shell對異常訊息的預設處理則是終止程式的執行並列印具體的出錯資訊,這也是在Python Shell中執行程式錯誤後所出現的出錯列印資訊的由來。

在try語句中,except與else程式碼塊都是可選的。except程式碼塊可以有0或多個;else程式碼塊可以有0或1個。但要注意,else語句的存在必須以except語句的存在為前提,在沒有except語句的try語句中使用else語句,會引發語法錯誤。

try語句中沒有else時,就構成try-except語句,如程式碼清單⑤所示。

程式碼清單⑤ try語句處理除零異常

In[6]:    number = 0
    # 以變數number作被除數,嘗試執行除法操作
    try:
        print('1.0 / number =', 1.0 / number)
    # 如果異常是除零異常,輸出提示資訊
    except ZeroDivisionError:
        print('***除數為0***') 

Out[6]:    ***除數為0***

在程式碼清單⑤中,由於0不能做除數,因此引發了除零異常。except程式碼塊由於給出了ZeroDivisionError的解決方案,因此被執行,程式得以完整地執行。

程式碼清單⑤所展示的異常之間的層次差別是有意義的,這在程式執行過程中可以體現,如程式碼清單⑥所示。

程式碼清單⑥ Python異常層次差異

In[7]:    dict1={'a': 1, 'b': 2, 'v': 22}
    # 嘗試索引賦值dict中不存在的值
    try:
        x = dict1['y']
    except LookupError:
        print('查詢錯誤')
    except KeyError:
        print('鍵錯誤')
    else:
        print(x)    


Out[7]:    查詢錯誤    


In[8]:    # 調換LookupError和KeyError處理程式碼塊的順序
    dict2={'a': 1, 'b': 2, 'v': 22}
    # 嘗試索引賦值dict中不存在的值
    try:
        x = dict2['y']
    except KeyError:
        print('鍵錯誤')
    except LookupError:
        print('查詢錯誤')
    else:
        print(x)    


Out[8]:    鍵錯誤

程式碼清單⑥展示的try-except-else語句嘗試查詢不在dict中的鍵值對,從而引發了異常。這一異常準確地說應屬於KeyError,但由於KeyError是LookupError的子類,且在程式碼清單⑥中將LookupError置於KeyError之前,因此程式優先執行該except程式碼塊。所以,使用多個except程式碼塊時,必須堅持對其規範排序,要從最具針對性的異常到最通用的異常。

除自然發生的異常外,Python中的raise語句可用於故意引發異常。使用該語句引發異常時,只需在raise後輸入異常名即可,如程式碼清單⑦所示。

程式碼清單⑦ raise語句

In[9]:    # 嘗試引發IndexError
    try:
        raise IndexError
    except KeyError:
        print ('in KeyError except')
    except IndexError:
        print('in IndexError except')
    else:
        print('no exception')   


Out[9]:    in IndexError except

相關文章