~~面向對象進階(七):異常捕獲~~


進擊のpython

*****

異常捕獲


什么叫做異常捕獲???我們分開來理解

什么是異常??什么又叫捕獲呢?


異常?那不是你經常做出來的嘛

不信??

你看看這些,你熟悉不??

NameError: name 'w' is not defined
ValueError: invalid literal for int() with base 10: 'w'
TypeError: 'int' object is not iterable
SyntaxError: Non-UTF-8 code starting with '\xce' in file
    ...

是不是都是你曾經的傑作呢???

吶,又要開始學新的英語單詞了

Error : 錯誤,異常

那么NameError就是變量異常

同理TypeError就是類型異常

看!一場是不是就出來了!

異常其實說白了不就是

你平時寫代碼出來的各種報錯嗎!

哈哈哈,扎鐵了老心!


那既然我們已經知道了什么是異常了

那捕獲呢?捕捉是個動詞是吧

(哥哥,你別告訴我你不知道這是動詞)

那我們為什么要捕獲異常呢?

一個最簡單的例子,我要輸入兩個數字,然后求和

因為用戶的輸入都是字符串類型是吧

(不知道???那我就想錘你了)

所以我們是不是還需要把字符串類型的數字變成整型

是不是就要用int()給他處理一下!

對吧!邏輯沒問題吧

但是你又發現了,我要是輸入的不是數字,就會給我報錯

然后程序就終止了!

但是我想做的是報錯了,我就跟他說你錯了,然后程序重新運行

這要求不過分吧!那么就要用到異常捕獲了!

如果你有異常,我就給你抓起來,不讓你報錯,那你程序不就能執行了嘛

如果我再想提示你個什么信息我就寫出來就完事了唄

那理論有了,我們來看看這玩仍到底怎么寫


兩個關鍵字 try except

while 1:
    try:
        m = int(input("請輸入第一個加數:"))
        n = int(input("請輸入第二個加數:"))
        print(m + n)
    except:
        print("請輸入數字")

用上面兩個關鍵字把你要捕捉異常的代碼放進去("就是你覺得可能會報錯的代碼塊!")

這個寫法格式就有點像 if-elif 的格式寫法

好了!基本的格式和寫法就是這樣的

但是啊,以你現在的技術,你就會報一個錯誤??

想什么呢湊弟弟!

還不是改一個又出來一個錯誤!

那這么多錯誤,我想針對不同的錯誤,有不同的提示

要怎么寫呢?????


這就用到了咱們最先的學到的那幾個英語單詞了

簡單來說就是用 不同的網抓不同的魚

我們有多少張網呢?

給你點常用的先感受一下

AttributeError 試圖訪問一個對象沒有的屬性,比如foo.x,但是foo沒有屬性x

IOError 輸入/輸出異常;基本上是無法打開文件

ImportError 無法引入模塊或包;基本上是路徑問題或名稱錯誤

IndentationError 語法錯誤(的子類) ;代碼沒有正確對齊

IndexError 下標索引超出序列邊界,比如當x只有三個元素,卻試圖訪問x[5]

KeyError 試圖訪問字典里不存在的鍵

KeyboardInterrupt Ctrl+C被按下

NameError 使用一個還未被賦予對象的變量

SyntaxError Python代碼非法,代碼不能編譯(個人認為這是語法錯誤,寫錯了)

TypeError 傳入對象類型與要求的不符合

UnboundLocalError 試圖訪問一個還未被設置的局部變量,基本上是由於另有一個同名的全局變量,導致你以為正在訪問它

ValueError 傳入一個調用者不期望的值,即使值的類型是正確的

再給你點不常用的,你看看就好

ArithmeticError

AssertionError

AttributeError

BaseException

BufferError

BytesWarning

DeprecationWarning

EnvironmentError

EOFError

Exception

FloatingPointError

FutureWarning

GeneratorExit

ImportError

ImportWarning

IndentationError

IndexError

IOError

KeyboardInterrupt

KeyError

LookupError

MemoryError

NameError

NotImplementedError

OSError

OverflowError

PendingDeprecationWarning

ReferenceError

RuntimeError

RuntimeWarning

StandardError

StopIteration

SyntaxError

SyntaxWarning

SystemError

SystemExit

TabError

TypeError

UnboundLocalError

UnicodeDecodeError

UnicodeEncodeError

UnicodeError

UnicodeTranslateError

UnicodeWarning

UserWarning

ValueError

Warning

ZeroDivisionError

我們有這么多張網,怎么用呢?

上面的程序,如果我輸入的是非數字是不是報的是ValueError

(你要不知道,你就把 try-except 去掉,然后輸入非數字,你看看提示的是什么)

(別的找錯方式也可以這樣!)

那我們就可以這么寫

while 1:
    try:
        m = int(input("請輸入第一個加數:"))
        n = int(input("請輸入第二個加數:"))
        print(m + n)
    except ValueError:
        print("請輸入數字")

為什么說是和 if-elif 相似的格式呢?

if-elif 是不是多選一啊

我們也可以!

while 1:
    try:
        k
        m = int(input("請輸入第一個加數:"))
        n = int(input("請輸入第二個加數:"))
        print(m + n)

    except ValueError:
        print("請輸入數字")

看,我是不是定義個變量,但是沒有賦值,那就回報這個錯誤:NameError: name 'k' is not defined

我們要是想抓這條魚,怎么做呢?多選一嘛!

while 1:
    try:
        k
        m = int(input("請輸入第一個加數:"))
        n = int(input("請輸入第二個加數:"))
        print(m + n)

    except ValueError:
        print("請輸入數字")
    except NameError:
        print("含有未定義的變量")

對吧!是不是寫法挺像 if-elif 的

如果你想兩個不同的錯誤都提示相同的信息

你也可以進行合寫!

except (ValueError,NameError)

那,是什么錯誤,都能捕獲嗎?????


a = 100
if a == 100:
print("hahah")

會報錯,報了一個什么錯呢? IndentationError: expected an indented block

那我們就用 try-except 來捕捉這個錯誤

練習自己捕捉!

你會發現這個錯誤你是捕捉不了的

其實不光是這個錯誤,還有些別的錯誤你也是捕捉不到的

什么語法錯誤 SyntaxError: invalid syntax 啊之類的

就等你自己發現啦!


那,很明顯

我要是錯誤很多,然后除了幾個錯誤之外,別的我都不想寫了

那我可以推薦你個好方法!萬能異常!

簡單來說就是一堵牆,它可以攔住漏過你前面網的所有魚

那既然我都這么說了

很明顯,這堵牆的位置應該在所有網的最后面

這堵牆長什么樣呢?

except Exception:

那除了那么寫的,還有別的

你想啊 if-elif 是不是后面還可以延伸一個else?

那try-except 也可以延伸出一個else

if-elif-else else是不是放在最后?

那 try-except-else 中的else也應該放在最后

if-elif-else 中的else是不是所有的都沒執行才執行else?

那try-except-else 中的else就應該是所有錯誤都沒出才執行!

對吧!類比學習嘛!


那除了除了以上的格式,其實還有別的

try-except-else-finally 多了個finally

那finally的作用其實就是你錯沒錯都是會執行的

(代碼自己敲!很簡單的)


那我們為了工作需要,有的時候也會主動拋出異常

那主動拋出異常就有要學一個詞了:raise

他就會拋出一個指定的異常,比如 raise NameError

就是我主動拋出一個叫做 NameError 的異常

那我主動拋出異常有什么用呢??

比如在以后的某天,你厲害了,自己寫了個軟件

那對於應用級的異常,就只能自己拋出特殊的異常

(而這個異常,往往是自己定義的,下面會提)

那這個時候就需要raise


我們可以學一下如何自定義一個異常

其實你定義的所有異常,都是繼承一個叫BaseException類

(你別告訴我你不知道繼承是啥)

我們可以把錯誤信息放在構造函數里面

    def __init__(self, msg):
        self.msg = msg

然后我們還要再寫一個這個

    def __Str__(self):
        return self.msg

最后我們進行拼裝一下,並進行測試

class MyError(BaseException):
    def __init__(self, msg):
        self.msg = msg

    def __Str__(self):
        return self.msg


try:
    raise MyError("我錯了!")
except MyError as e:
    print(e)

自己看結果

同時啊,這里還要強調一點

就是這種自己搞得異常,萬能異常都是捕捉不到的!


*別走開*
*下節更精彩*


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM