在編寫計(jì)算機(jī)程序時(shí),通常能夠區(qū)分正常和異常(不正常)情況。異常事件可能是錯(cuò)誤(如試圖除以零),也可能是通常不會(huì)發(fā)生的事情。Python使用異常對(duì)象來表示異常狀態(tài),并在遇到錯(cuò)誤時(shí)引發(fā)異常。異常對(duì)象未被處理(或捕獲)時(shí),程序?qū)⒔K止并顯示一條錯(cuò)誤消息(traceback)。
#試圖除以零的報(bào)錯(cuò)
print(1/0)
# Traceback (most recent call last):
# print(1/0)
# ZeroDivisionError: division by zero
正如你所見,出現(xiàn)問題是,自動(dòng)引發(fā)異常。要引發(fā)異常,可使用raise語句,并將一個(gè)類(必須是Exception的子類)或者實(shí)例作為參數(shù),將類作為參數(shù)時(shí),將自動(dòng)創(chuàng)建一個(gè)實(shí)例。
raise Exception
# Traceback (most recent call last):
# raise Exception
# Exception
raise Exception("error occurred ")
# Traceback (most recent call last):
# raise Exception("error occurred ")
# Exception: error occurred
在第一個(gè)示例(raise Exception)中,引發(fā)的時(shí)通常異常,并沒有指出來出現(xiàn)了什么錯(cuò)誤。在第二個(gè)示例中,添加了錯(cuò)誤消息error occurred。 幾乎所有的異常類都是由Exception派生出來的。
| 常見類名 | 描述 |
| KeyboardInterrupt | 用戶中斷執(zhí)行(通常是輸入Ctrl+C) |
| ArithmeticError | 引用屬性或給它賦值失敗時(shí)引發(fā) |
| ZeroDivisionError | 在除法或求模運(yùn)算的第二個(gè)參數(shù)為零時(shí)引發(fā) |
| ImportError | 導(dǎo)入模塊/對(duì)象失敗 |
| IndexError | 序列中沒有此索引(index) |
| TypeError | 將內(nèi)置操作或函數(shù)用于類型不正確的對(duì)象時(shí)引發(fā) |
?
-
捕獲異常
在編寫代碼的時(shí)候,出現(xiàn)異常可以對(duì)其進(jìn)行一定的處理,而在處理之前,我們通常要對(duì)其進(jìn)行捕獲,稱之為 捕獲異常 。可以使用try/except語句。(此時(shí)還是以ZeroDivisionError為例,演示如何捕獲異常)
x = float(input("Enter the first number:")) #用戶輸入的內(nèi)容為str型,需對(duì)其進(jìn)行強(qiáng)轉(zhuǎn),int或者float均可
y = float(input("Enter the second number:"))
print(x/y)
# Traceback (most recent call last):
# print(x/y)
# ZeroDivisionError: float division by zero
print(x%y)
# Traceback (most recent call last):
# print(x%y)
# ZeroDivisionError: float modulo
這個(gè)程序運(yùn)行正常,直到用戶在第二個(gè)參數(shù)輸入0,對(duì)于第二個(gè)參數(shù)輸入值為0這種異常狀態(tài)時(shí),使用try/except進(jìn)行捕獲異常(這里打印一條對(duì)用戶更友好的錯(cuò)誤消息)。
try:
x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x/y)
except:
print("The sceond number can't be zero!")
"""
Enter the first number:1
Enter the second number:0
The sceond number can't be zero!
"""
或許使用if來判斷y值好像簡(jiǎn)單許多,就本例而言,這可能也是更佳的解決方案,因?yàn)檫@個(gè)程序執(zhí)行的除法運(yùn)算越多,則每條除法運(yùn)算都需要一條if進(jìn)行判斷,無疑增加其空間復(fù)雜度(O(n)),而使用try/except只需要一個(gè)錯(cuò)誤處理程序。
發(fā)生除零行為時(shí),如果啟用了“抑制”功能,將返回None,換言之,如果啟用“抑制”功能,將不應(yīng)依賴返回值。關(guān)閉“抑制”功能時(shí),捕獲異常ZeroDivisionError
class MuffledCalculator:
muffled = False # 抑制
def calc(self,expr):
try:
return eval(expr)
except ZeroDivisionError:
if self.muffled:
print('Division by zero is illegal')
else:
raise
# eval() 函數(shù)用來執(zhí)行一個(gè)字符串表達(dá)式,并返回表達(dá)式的值。
c = MuffledCalculator()
print(c.calc('10/2'))
# 5.0
print(c.calc('10/0')) #關(guān)閉抑制,報(bào)錯(cuò)
# ZeroDivisionError: division by zero
c.muffled = True
print(c.calc('10/0'))
# Division by zero is illegal
# None
如果無法處理異常,在except子句中使用不帶參數(shù)的raise通常是不錯(cuò)的選擇,有時(shí)你可能想引發(fā)別的異常,在這種情況下,導(dǎo)致進(jìn)入except子句的異常將作為異常上下文儲(chǔ)存起來,并出現(xiàn)在最終的錯(cuò)誤消息中。
-
證明except在處理異常優(yōu)于if
x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x/y)
"""
Enter the first number:10
Enter the second number:python
ValueError: could not convert string to float: 'python'
"""
對(duì)于這種情況,用戶在第二個(gè)參數(shù)輸入的為字符串或者其他類型的數(shù)據(jù),此時(shí)使用if來判斷還是最優(yōu)的解嗎?對(duì)于任何可能出現(xiàn)的異常進(jìn)行判斷和捕獲。
try:
x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x/y)
except ZeroDivisionError:
print("The sceond number can't be zero!")
except TypeError:
print("Please change a data type")
except ValueError:
print("That wasn't a number,was it?")
僅當(dāng)有異常時(shí)才會(huì)中斷輸入
while True:
try:
x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x / y)
except:
print("Invalid input,Please try again")
break
僅當(dāng)沒有引發(fā)異常時(shí),才會(huì)跳出循環(huán),只要出現(xiàn)錯(cuò)誤,程序就會(huì)要求用戶提供新的輸入
while True:
try:
x = float(input("Enter the first number:"))
y = float(input("Enter the second number:"))
print(x / y)
except:
print("Invalid input,Please try again")
else:
break
"""
Enter the first number:a
Invalid input,Please try again
Enter the first number:1
Enter the second number:0
Invalid input,Please try again
Enter the first number:10
Enter the second number:2
5.0
"""
-
finally的用法
'''
try:
執(zhí)行代碼
except:
如果有異常發(fā)生,執(zhí)行此處的代碼
else:
如果沒有異常發(fā)生,執(zhí)行此處代碼
finally:
不管有沒有異常都會(huì)執(zhí)行此處代碼
'''
-
自定義異常類
自定義的異常類必須是Exception或者Error的子類!!!
class My_Exception(Exception):
'''
Custom exception types
'''
def __init__(self, parameter, para_value):
my_error = 'The parameter "{0}" is not legal:{1}'.format(parameter, para_value)
Exception.__init__(self, my_error)
self.parameter = parameter
self.para_value = para_value
對(duì)于warnings警告模塊,最后結(jié)尾說兩句:
import warnings
warnings.warn("I've got a bad feeling about this.")
# warnings.filters() 用于過濾警告
# warnings.warn 用于發(fā)出警告
-
小結(jié):
- 異常對(duì)象:異常情況時(shí)用異常對(duì)象表示的。對(duì)于異常情況,有多種處理方式;如果忽略,將導(dǎo)致程序終止。
- 引發(fā)異常:可使用raise語句來引發(fā)異常,它將一個(gè)異常類或者異常實(shí)例作為參數(shù),也可以使用excerpt同時(shí)判斷多個(gè)異常情況(上面有示例)。如果在except子句中調(diào)用raise時(shí)沒有提供任何參數(shù),它將重新引發(fā)該子句捕獲異常。
- 自定義的異常類:通過Exception派生出來的自定義異常類
-
捕獲異常:要捕獲異常,可在try語句中使用except子句,在except子句中,如果沒有指定異常類,將捕獲所有的異常。也可以指定多個(gè)異常類,將其放在 元組 中。
-
else子句:除except子句外,還可以使用else子句,在主try塊沒有引發(fā)異常時(shí)執(zhí)行。
-
finally子句:確保代碼塊無論怎么樣都可以執(zhí)行異常,可以用try/finally,將代碼塊放在finally子句中。
-
警告:警告類似于異常,但是通常只打印一條錯(cuò)誤消息,可以指定警告類別,因?yàn)樗鼈兪? Warning 的子類。
按照我的python版本找到了關(guān)于warning的文檔。需要請(qǐng)參考!
Warning文檔
?
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元

