FishC筆記—32 講 異常處理:你不可能總是對的

本期內容詳解:

Python標準異常總結

異常 說明
AssertionError 斷言語句(assert)失敗
AttributeError 嘗試訪問未知的對象屬性
EOFError 用戶輸入文件末尾標誌EOF(Ctrl+d)
FloatingPointError 浮點計算錯誤
GeneratorExit Gengeator.close()方法被調用的時候
ImportError 導入模塊失敗的時候
IndexError 索引超出序列的範圍
KeyError 字典中查找一個不存在的關鍵字
KeyboardError 用戶輸入中斷鍵(Ctrl+c)
MemoryError 內存溢出(可通過刪除對象釋放內存)
NameError 嘗試訪問一個不存在的變量
NotImplementedError 尚未實現的方法
OSError 操作系統產生的異常(例如打開一個不存在的文件)
OverflowError 數值運算超出最大限制
ReferenceError 弱引用(weak reference)試圖訪問一個已經被垃圾回收幾隻回收了的對象
RuntimeError 一般的運行時錯誤
StopIteration 迭代器沒有更多的值
SyntaxError Python的語法錯誤
IndentationError 縮進錯誤
TabError Tab和空格混合使用
SystemError Python編譯器系統錯誤
SystenExit Python編譯器進程被關閉
TypeError 不同類型間的無效操作
UnboundLocalError 訪問一個未初始化的本地變量(NameError的子類)
UnicodeError Unicode相關的錯誤(ValueError的子類)
UnicodeEncodeError Unicode編碼時的錯誤(UnicodeError的子類)
UnicodeDecodeError Unicode解碼時的錯誤(UnicodeError的子類)
UnicodeTranslateError Unicode轉換時的錯誤(UnicodeError的子類)
ValueError 傳入無效的參數
ZeroDivisionError 除數爲零

以下是 Python 內置異常類的層次結構:

典型課後題
結合你自身的編程經驗,總結下異常處理機制的重要性?

答:由於環境的不確定性和用戶操作的不可以預知性都可能導致程序出現各種問題,因此異常機制最重要的無非就是:
增強程序的健壯性和用戶體驗,儘可能的捕獲所有預知的異常並寫好處理的代碼,當異常出現的時候,程序自動消化並恢復正常(不至於崩潰)。

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    >>> my_list = [1, 2, 3, 4,,]  

答:語法錯誤SyntaxError: invalid syntax

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    >>> my_list = [1, 2, 3, 4, 5]  
    >>> print(my_list[len(my_list)])  

答:len(my_list) 是獲得列表的長度,這裏長度爲5,該列表各個元素的訪問索引號分別是:[0, 1, 2, 3, 4],因此試圖訪
問 my_list(5) 會引發 IndexError: list index out of range 異常。

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    >>> my_list = [3, 5, 1, 4, 2]  
    >>> my_list.sorted()  

答:初學者容易疏忽的錯誤,列表的排序方法叫 list.sort(),sorted() 是BIF。因此會引發 AttributeError: ‘list’ object
has no attribute ‘sorted’ 異常。

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    >>> my_dict = {'host': 'http://bbs.fishc.com', 'port': '80'}  
    >>> print(my_dict['server'])  

答:嘗試訪問字典中一個不存在的“鍵”引發 KeyError: ‘server’ 異常,爲了避免這個異常發生,可以使用 dict.get() 方法:

    if not my_dict.get('server'):  
            print('您所訪問的鍵【server】不存在!')  

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    def my_fun(x, y):  
            print(x, y)  

    f(x=1, 2)  

答:如果使用關鍵字參數的話,需要兩個參數均使用關鍵字參數 f(x=1, y=2)

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    f = open('C:\\test.txt', wb)  
    f.write('I love FishC.com!\n')  
    f.close()  

答:注意 open() 第二個參數是字符串,應該 f = open(‘C:\test.txt’, ‘wb’) 。wb不加雙引號 Python 還以爲是變量名呢,往上一找,艾瑪沒找着……引發 NameError 異常。由於打開文件失敗,接着下邊一連串與 f 相關的均會報同樣異常。

請問以下代碼是否會產生異常,如果會的話,請寫出異常的名稱:

    def my_fun1():  
            x = 5  
            def my_fun2():  
                    x *= x  
                    return x  
            return my_fun2()  

    my_fun1()  

答:閉包的知識大家還記得不? Python 認爲在內部函數的 x 是局部變量的時候,外部函數的 x 就被屏蔽了起來,所以執行 x *= x 的時候,在右邊根本就找不到局部變量 x 的值,因此報錯。

在 Python3 之前沒有直接的解決方案,只能間接地通過容器類型來存放,因爲容器類型不是放在棧裏,所以不會被“屏蔽”掉。容器類型這個詞兒大家是不是似曾相識?我們之前介紹的字符串、列表、元祖,這些啥都可以往裏的扔的就是容器類型啦。

於是乎我們可以把代碼改造爲:

    def my_fun1():  
            x = [5]  
            def my_fun2():  
                    x[0] *= x[0]  
                    return x[0]  
            return my_fun2()  

    my_fun1()  

但是到了 Python3 的世界裏,又有了不少的改進,如果我們希望在內部函數裏可以修改外部函數裏的局部變量的值,
那麼也有一個關鍵字可以使用,就是 nonlocal:

    def my_fun1():  
            x = 5  
            def my_fun2():  
                    nonlocal x  
                    x *= x  
                    return x  
            return my_fun2()  

    my_fun1()  
發佈了89 篇原創文章 · 獲贊 316 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章