資源簡介 (共40張PPT)Python少兒編程第九章 一起捉bug目錄1.1什么是bug1.2如何捉bug1.3主動拋出bug1.4自己也可以定義bugPART 01什么是bug語法錯誤1.1語法錯誤也稱為解析錯誤,在使用PyCharm編寫代碼時,如果出現語法錯誤,會通過紅色波浪線提示。常見的語法錯誤包括拼寫錯誤、縮進錯誤等不符合Python語法規范的錯誤。例如,變量名使用數字開頭,if語句后沒有冒號,錯誤提示如圖9-1所示。從圖9-1中可以看出,“1name = '小藍'”語句由于變量名使用數字開頭,所以出現錯誤提示。“if age < 18”語句由于最后缺少冒號,也出現錯誤提示,此時,將鼠標放到錯誤提示位置,會給出錯誤原因或解決方法。異常1.2即使Python程序的語法是正確的,在運行時也有可能發生錯誤,這種在運行期間檢測到的錯誤稱為異常。Python的異常分為兩種:一種是內置異常,在某些錯誤出現時會自動觸發;另一種是用戶自定義異常(詳見9.4節),就是用戶根據自己的需求設置的異常。常見的內置異常如表9-1所示。表9-1 Python中常見的內置異常異常1.2表9-1 Python中常見的內置異常(續)異常1.2大多數異常不會被程序自動處理,會以異常信息的形式進行顯示。例如,執行“a = '2' + 3”語句,出現的異常信息如圖9-2所示。圖9-2 異常信息從圖9-2可以看出,該語句拋出了TypeError異常,如果沒有對該異常進行處理,程序就會使用所謂的回溯(Traceback,一種異常信息)終止執行,這些信息包括異常發生的行號、異常的名稱(如TypeError)和原因等。PART 02如何捉bugtry-except語句2.1try-except語句用于捕獲和處理異常,其語法格式如下。try:#可能會引發異常的代碼塊except exception [as e]:#出現異常后執行的代碼塊其中,exception為異常類名,[]為可選項,“as e”表示將異常類的實例對象命名為e。如果try子句中的代碼塊引發異常并被except子句捕獲,就執行except子句中的代碼塊;如果try子句中的代碼塊沒有引發異常,就繼續執行try-except語句后面的代碼;如果引發的異常沒有被except子句捕獲,程序將終止運行并輸出異常信息。try-except語句2.1【例9-1】 捕獲除數為0的異常。【問題分析】 在try子句中輸入被除數和除數,然后進行除法運算,并輸出商;except子句捕獲ZeroDivisionError異常,并輸出異常信息。【參考代碼】try:a = float(input('請輸入被除數:'))b = float(input('請輸入除數:'))c = a / bprint('商為:', c)except ZeroDivisionError:print('除數不能為0!')try-except語句2.1【運行結果】 運行程序,輸入被除數為2,除數為1,結果如圖9-3所示;再次運行程序,輸入被除數為2,除數為0,結果如圖9-4所示。圖9-3 例9-1程序運行結果1 圖9-4 例9-1程序運行結果2【程序說明】 從運行結果可以看出,當除數為0時,程序引發ZeroDivisionError異常,此時,except子句捕獲了這個異常并輸出“除數不能為0!”。由于程序對異常進行了處理,所以沒有出現終止運行并拋出異常的情況。try-except語句2.1也可通過異常類的實例對象直接輸出異常信息。例如,將例9-1的except子句做如下修改。except ZeroDivisionError as e:print(e)再次運行例9-1,結果如圖9-5所示。圖9-5 例9-1程序修改后的運行結果多重except語句2.2在某些情況下,一個代碼塊可能引發多種異常,此時,可定義多個except子句,每個except子句捕獲一種類型的異常,其語法格式如下。try:#可能會引發異常的代碼塊except exception1 [as e]:#處理異常類型1的代碼塊except exception2 [as e]:#處理異常類型2的代碼塊except exception3 [as e]:#處理異常類型3的代碼塊…當異常發生時,依次檢查每一個except子句,并執行第一個異常類型匹配的代碼塊,其他的except子句將不再捕獲,程序繼續執行try-except語句后面的代碼。多重except語句2.2【例9-2】 在例9-1的基礎上,捕獲參數類型不正確異常。【參考代碼】try:a = float(input('請輸入被除數:'))b = float(input('請輸入除數:'))c = a / bprint('商為:', c)except ZeroDivisionError:print('除數不能為0!')except ValueError:print('被除數和除數應為數字類型!')多重except語句2.2【運行結果】 運行程序,輸入被除數為2,除數為x,結果如圖9-6所示。圖9-6 例9-2程序運行結果【程序說明】 上述代碼中,輸入的除數為非數字類型,導致程序出現ValueError異常,并被第二個except子句捕獲,所以輸出“被除數和除數應為數字類型!”。如果沒有第二個except子句,程序將由于沒有處理新異常的語句而導致終止運行并拋出異常。try-except-else語句2.3try-except語句還有一個可選的else子句,如要使用該子句,須將其放在所有except子句后。else子句將在try子句沒有發生任何異常時執行,其語法格式如下。try:#可能會引發異常的代碼塊except exception [as e]:#出現異常后執行的代碼塊else:#如果try子句中的代碼沒有引發異常,則執行該代碼塊try-except-else語句2.3【例9-3】 以只讀方式打開文件,并統計文件中文本的行數,如果文件不存在則給出提示信息。【參考代碼】fileName = 'birthday.txt'try:file = open(fileName, 'r')except FileNotFoundError:print(fileName, '文件不存在')else:print(fileName, '文件有', len(file.readlines()), '行')file.close()try-except-else語句2.3【運行結果】 運行程序,如果文件“birthday.txt”不存在,結果如圖9-7所示;如果文件“birthday.txt”存在,且有6行文本,結果如圖9-8所示。圖9-7 例9-3程序運行結果1 圖9-8 例9-3程序運行結果2try-except-finally語句2.4finally子句用于為異常處理提供一個統一的出口,無論try子句中的代碼是否引發異常,都會執行該子句。通常,finally子句用于資源清理工作,如釋放內存、關閉打開的文件、斷開網絡連接等,其語法格式如下。try:#可能會引發異常的代碼塊except exception [as e]:#出現異常后執行的代碼塊finally:#無論try子句中的代碼是否引發異常,都會執行的代碼塊try-except-finally語句2.4【例9-4】 將輸入的整數寫入文件,要求無論是否捕獲到異常,都會執行關閉文件的操作。【參考代碼】fileName = 'integer.txt'try:file = open(fileName, 'a')data = int(input('請輸入一個整數:'))file.write(str(data))except Exception as e:print(e)finally:print('關閉文件')file.close()try-except-finally語句2.4【運行結果】 運行程序,輸入5,結果如圖9-9所示;再次運行程序,輸入9.6,結果如圖9-10所示。圖9-9 例9-4程序運行結果1 圖9-10 例9-4程序運行結果2【程序說明】 從運行結果可以看出,輸入整數5時,try子句中代碼沒有引發異常,會跳過except子句執行finally子句中的代碼。輸入浮點數9.6時,try子句中代碼引發異常,則會先執行except子句中的代碼,再執行finally子句中的代碼??傊?,無論如何finally子句中的代碼都要執行。PART 03主動拋出bugraise語句3.1raise語句可拋出一個指定的異常,其語法格式如下。raise [exception[(message)]]其中,exception表示異常類名,message表示異常對象的描述信息,[]表示參數可選。使用raise語句拋出指定異常時,須使用try-except語句捕獲拋出的異常,否則程序會終止,并顯示異常信息。raise語句根據參數的不同有下面3種用法。raise語句3.1(1)exception和message都存在,在指定異常類型的同時,設置異常對象的描述信息。【例9-5】 創建通訊錄。【問題分析】 try-except語句包含在循環中,try子句中使用len()函數檢測號碼是否為11位,使用isdigit()函數檢測號碼是否只包含數字,并分別使用raise語句拋出Exception異常,設置相應的異常信息,如果號碼格式正確,則寫入文件;except子句捕獲異常并輸出異常信息。raise語句3.1【參考代碼】while True:try:name = input('請輸入姓名:')phone = input('請輸入手機號碼:')if len(phone) != 11:raise Exception('手機號必須為11位。')if not phone.isdigit():raise Exception('手機號必須為數字。')with open('PhoneBook.txt', 'a') as file:file.write(name + '\t' + phone + '\n')except Exception as e:print('異常信息:', e)raise語句3.1【運行結果】 程序運行結果如圖9-11所示。圖9-11 例9-5程序運行結果【程序說明】 從運行結果可以看出,程序捕獲了異常并輸出了設置的異常信息,且程序沒有終止運行,繼續循環。raise語句3.1(2)message缺省,只指定異常類型。此時,捕獲異常后無法輸出異常信息。例如,基于例9-5,刪除異常的描述信息,修改代碼如下。if len(phone) != 11:raise Exception()if not phone.isdigit():raise Exception()再次運行例9-5,程序運行結果如圖9-12所示。從圖9-12可以看出,輸入的手機號碼格式不對時,程序雖然捕獲到異常,但是無法輸出異常信息。圖9-12 message缺省時例9-5程序運行結果raise語句3.1(3)exception和message都缺省,只有一個單獨的raise。此時,捕獲到異常后,將重新引發它(傳遞異常)。例如,基于例9-5,在except子句的末尾添加raise語句,修改代碼如下。except Exception as e:print('異常信息:', e)raiseraise語句3.1再次運行例9-5,程序運行結果如圖9-13所示。圖9-13 重新引發異常的運行結果從圖9-13可以看出,輸入的手機號碼格式不對時,程序捕獲到異常并輸出了異常信息。由于在except子句中使用單獨的raise語句重新引發了該異常,且沒有捕獲,所以程序終止運行并輸出了異常信息。assert語句3.2assert語句又稱為斷言,它是對一個邏輯表達式進行檢查,如果為False,就會觸發AssertionError異常,其語法格式如下。assert expression [,message]assert后面緊跟邏輯表達式,message為一個字符串,當表達式的值為False時,作為異常類的描述信息使用。邏輯上等同于:if not expression:raise AssertionError(message)assert語句用于收集用戶定義的約束條件,而不是捕獲內在的程序設計錯誤。assert語句3.2【例9-6】 將百分制成績轉換成五級制成績輸出,使用assert語句判斷輸入的百分制成績是否處于0~100。【參考代碼】while True:try:score = int(input('請輸入百分制成績:'))#斷言score處在0~100,如果不是拋出異常assert score >= 0 and score <= 100, '分數必須處于1~100'if score >= 90:print('優')assert語句3.2【參考代碼】(續)elif score >= 80:print('良')elif score >= 70:print('中')elif score >= 60:print('及格')else:print('不及格')except Exception as e:print('異常信息:', e)break #跳出循環assert語句3.2【運行結果】 程序運行結果如圖9-14所示。圖9-14 例9-6程序運行結果【程序說明】 整個程序位于while循環內部,循環中通過try-except語句進行異常處理。在try子句中,通過鍵盤獲取了int類型的數據score,然后斷言score的值必須處于0~100。如果輸入的數據不處于0~100,則會拋出AssertionError異常,從而執行except子句,輸出提示信息并跳出循環,結束程序。PART 04自己也可以定義bug自己也可以定義bug4Python提供的內置異常可以描述大部分異常情況,但有時程序會有特殊的要求,系統可能無法識別該異常,此時,需要用戶創建自定義異常類,使系統能夠識別異常并進行處理。自定義異常類必須繼承Exception類,通過__init__()方法初始化異常類對象,然后通過__str__()方法返回異常類對象說明信息。自定義異常類通過raise語句拋出,捕獲異常后可直接通過異常對象輸出說明信息。自己也可以定義bug4【例9-7】 體質指數(BMI)的計算公式為:BMI=體重/身高2,其中體重的單位為kg,身高的單位為m。編寫程序,輸入一個人的身高和體重,如果BMI小于18.5則輸出“消瘦”,處于18.5~24(不含)則輸出“正?!?,處于24~28(不含)則輸出“超重”,28及以上則輸出“肥胖”。要求自定義異常類處理身高小于0.3 m、大于2.5 m的異常情況。【參考代碼】import math #導入math模塊class HeightException(Exception):def __init__(self, value):self.value = valuedef __str__(self):return '異常信息:身高應處于0.3~2.5,輸入的身高是:{}'\.format(self.value)自己也可以定義bug4【參考代碼】(續)def computeBMI():height = float(input('請輸入身高:'))if height < 0.3 or height > 2.5:raise HeightException(height) #拋出異常weight = float(input('請輸入體重:'))BMI = weight / math.pow(height, 2) #計算BMI指數if BMI < 18.5: #如果BMI小于18.5,輸出“消瘦”print('消瘦');elif BMI < 24: #如果BMI小于24且大于等于18.5,輸出“正常”print('正常');elif BMI < 28: #如果BMI小于28且大于等于24,輸出“超重”print('正常');else: #如果BMI大于等于28,輸出“肥胖”print('肥胖');自己也可以定義bug4【參考代碼】(續)#異常處理try:computeBMI()except HeightException as e:print(e)except ValueError:print('輸入的數據異常,請輸入浮點數或整數!')自己也可以定義bug4【運行結果】 運行程序,當輸入身高為1.8時,程序正常運行,結果如圖9-15所示;當輸入身高為3時,拋出異常,結果如圖9-16所示。圖9-15 例9-7程序運行結果1 圖9-16 例9-7程序運行結果2【程序說明】 第2~6行定義了HeightException異常類繼承Exception類,value表示實際輸入的值。若用戶輸入的身高不符合規范時,就會拋出HeightException異常。感謝觀看 展開更多...... 收起↑ 資源預覽 縮略圖、資源來源于二一教育資源庫