1. 程式人生 > >2018.11.1

2018.11.1


"""
1. 什麼是異常?
異常是錯誤發生前的一種訊號
如果沒有人來處理這個訊號 程式就會中斷執行並丟擲錯誤資訊

異常的分類:
1.語法檢查異常 這種異常是最低階異常 絕對不應該犯
也非常好避免
如果是編譯器 會自動提示
如果是文字編輯器 在你執行程式碼前 直譯器會檢查語法
2.執行時異常(邏輯異常)
這種異常只有在程式碼被執行時才能發現
我們要處理的重點就是執行時異常
特點:在沒有執行程式碼前 是無法發現的
如果執行時異常已經發生並且沒有正確處理他 就丟擲錯誤資訊
並且中斷程式的執行 這是要我們學習異常解決的問題
異常的組成
1.追蹤資訊 (具體發生異常的位置 以及函式的呼叫順序)
2.異常的型別 (錯誤的型別)
3.異常的訊息 (詳細的錯誤資訊)

我們之所以學習異常處理
為的是讓我們的程式更加穩定 (健壯性) 不容易崩潰
### 你不清楚為什麼會發生異常! 這時候用try


"""

2常見的發生原因:
NameError 找不到這個名字 要麼變數 要麼函式
ValueError 在呼叫一個函式時給的的值不正確
TypeError 型別錯誤 例如字串與數字加減乘除 呼叫一個不能被呼叫的型別
ZeroDivisionError 除數不能為0
KeyError 沒有這個key
IndexError 索引不存在
StopIteration 沒有更多的值可以迭代
FileNotFoundError 檔案不存在
io.UnsupportedOperation 檔案的操作不支援
AttributeError 沒有這個屬性
KeyboardInterrupt 程式被強行終止 ctrl+c
更多可以在部落格裡看到

"""
3要處理異常
要學的就是一個新的語法

今後使用最多的寫法:
try:
這裡放可能出現異常的程式碼
except: 異常的型別:
當異常發生並且異常型別匹配時
執行except中的程式碼
注意:一旦try中有程式碼丟擲了異常 後面的程式碼全都不執行

練習: 捕獲某種型別的異常 捕獲任意類異常 感受一下執行順序
"""
# 當代碼可能出現多種異常時的寫法
# print("staring.....")
# try:


"""
4不太常用的
語法1
try:
except:
else: try中沒有發生異常時執行

語法2
try :
except :
finally : 無論是否發生異常 都會執行finally 可以用來回收系統資源!
"""
# print("start...")
# try:
# # 1/0
# [][1]
# pass
# except ZeroDivisionError:
# print("除數異常")
# except NameError:
# print("名字異常")
# else:
# print("else會在 try中沒有異常時執行")
# print("end...")


# finally
# print("start...")
# try:
# # 1/0
# # [][1]
# pass
# except ZeroDivisionError:
# print("除數異常")
# except IndexError:
# print("索引異常")
# else:
# print("else會在 try中沒有異常時執行")
# finally:
# print("finally 無論異常是否發生 都會執行!")
# print("end...")


# 使用finally來回收資源
try:
f = open(r"D:\上海python全棧4期\day31\異常處理\1今日內容","rt",encoding="utf-8")
f.read()
# f.write("123")
except Exception:
print("發生異常了")
finally:
print("關閉檔案!")
f.close()
print(f.closed)

# # name
# # [][-1]
# 1/0
# pass
# except NameError:
# print("名字找不到!")
# except IndexError:
# print("索引超出範圍")
# except ZeroDivisionError:
# print("除數不能為0")
# print("end.......")

# 當代碼可能出現多種異常時的寫法2
# print("staring.....")
# try:
# {}["aaa"]
# # name
# # [][-1]
# 1/0
# except (NameError,IndexError,ZeroDivisionError):
# print("可能名字找不到! 可能所以超出範圍 可能除數為0")
# print("end.......")

# 上面兩種寫法 都可以處理多種異常 但是 異常型別太多了 不可能全寫完
# 萬能異常型別 Exception 或BaseException 基於OOP的繼承和多型
print("staring.....")
try:
# {}["aaa"]
# name
# [][-1]
1/0
except Exception:
print("可能名字找不到! 可能所以超出範圍 可能除數為0")
print("end.......")

5 當程式中有一些限制 然而使用者沒有遵守 我們可以主動丟擲異常
語法:
raise 異常型別(異常的詳細資訊)
型別必須是BaseException的子類
"""
# raise NameError("這就是名字不存在異常!")

age = input("請輸入整型的年齡:")
if not age.isdigit():
raise TypeError("你輸入的不是整型!")
age = int(age)
print("十年後你%s歲" % (age + 10))

"""
6 斷言 可以理解斷定 就是很清楚 很明確
什麼時候需要斷定?
下面的程式碼必須依賴上面程式碼的正確資料
語法: assert 結果為Bool的表示式
如果值為True 則繼續往下執行
為False 丟擲一個 AssertionError 表示斷言失敗
沒有assert 也可以使用if來玩 assert 僅僅是簡化了程式碼

"""

# 第一部分程式碼 負責產生一個列表
li = []
# li.append(1)
# li.append(2)
# 這裡一定要確保資料是有效的
# if len(li) < 1:
# raise ValueError("列表中沒有資料!")
assert len(li) > 0
# 需要使用列表中的資料來完成任務 如果沒有資料無法完成
print(li[0])
print(li[0])
print(li[0])
print(li[0])

7" 當系統提供的這些異常型別 和你要描述的錯誤不匹配時 就需要自定義異常型別
寫法:
class 自定義異常型別名稱(BaseException):
總結一下:之所以自定義異常型別 是為了更具體描述你的錯誤 讓使用者一眼就看出了

關鍵點:1.如何自定義異常型別
2.在except中 使用as 來獲取異常物件

"""
# 你隨便輸入一句話 看我喜不喜歡 不喜歡我就丟擲異常
# 自定義異常類
class UnlikeError(BaseException):
def __init__(self,msg,text):
self.msg = msg
self.text = text
# 函式中可能丟擲異常
def hello():
text = input("輸入一段話:")
if text == "你真帥":
print("你說得對!")
else:
raise UnlikeError("你再看看...","另一個引數")
# 捕獲異常
try:
hello()
# 獲取異常物件
except UnlikeError as e:
print(e.text)