異常
異常就是程序運行錯誤或者邏輯混亂。不能讓用戶看到直接代碼的報錯,需要給客戶友好的提示。
異常一般是程序中無法完全避免,一般通過一定的手段,盡量減少異常的發(fā)生。提高代碼的健壯性。
例如:
open('1.txt','r')
當Python檢測到一個錯誤時,解釋器就無法繼續(xù)執(zhí)行了,反而出現(xiàn)了一些錯誤的提示,這就是所謂的"異常"。
捕獲異常
捕獲異常 try...except...
try:
? ? print('***********1**********')
? ? open('./1.txt','r') #如果此行報錯,那么下一行就不再運行,直接被except捕獲
? ? print('***********2**********')
except Exception as ex:
? ? print('[Error]:%s'%ex)
說明:
此程序看不到任何錯誤,因為用except 捕獲到了IOError異常,并添加了處理的方法。
把可能出現(xiàn)問題的代碼,放在try中
把處理異常的代碼,放在except中
捕獲多個異常
try:
? ? print('***********1**********')
? ? open('./捕獲異常.py','r') #如果此行報錯,那么下一行就不再運行,直接被except捕獲
? ? print('***********2**********')
? ? print(num)
? ? print('***********3**********')
except IOError as result:
? ? print('[Error]:%s'%result)
except NameError as result: #對異常信息的描述
? ? print('[error]:%s'%result) #打印異常信息
如果有多個異常,可以將要捕獲的異常名字放在except后邊,使用元組進行存儲,也可以寫多個except
else
咱們應該對else并不陌生,在if中,它的作用是當條件不滿足時執(zhí)行的實行;同樣在try...except...中也是如此,即如果沒有捕獲到異常,那么就執(zhí)行else中的事情。
try:
? ? print('***********1**********')
? ? open('./捕獲異常.py','r') #如果此行報錯,那么下一行就不再運行,直接被except捕獲
? ? print('***********2**********')
? ? print('num')
? ? print('***********3**********')
except IOError as result:
? ? print('[Error]:%s'%result)
except NameError as result:
? ? print('[error]:%s'%result)
else: #如果沒有捕獲到異常,那么就執(zhí)行else中的事情
? ? print('No Error,Happy!')
try...finally...
try...finally...語句用來表達這樣的情況:
在程序中,如果一個段代碼必須要執(zhí)行,即無論異常是否產(chǎn)生都要執(zhí)行,那么此時就需要使用finally。 比如文件關閉,釋放鎖,把數(shù)據(jù)庫連接返還給連接池等。
import time
try:
? ? file = open('./捕獲異常.py','rb')
? ? try:
? ? ? ? contents = file.readlines()
? ? ? ? for content in contents:
? ? ? ? ? ? time.sleep(1)
? ? ? ? ? ? print(content)
except Exception as result:
? ? print('[Error]:%s'%result)
finally:
? ? file.close()
? ? print('關閉文件!')
except:
? ? print('no file!')
說明:
test.txt文件中每一行數(shù)據(jù)打印,但是我有意在每打印一行之前用time.sleep方法暫停1秒鐘。這樣做的原因是讓程序運行得慢一些。在程序運行的時候,按Ctrl+c中斷(取消)程序。
我們可以觀察到KeyboardInterrupt異常被觸發(fā),程序退出。但是在程序退出之前,finally從句仍然被執(zhí)行,把文件關閉。
異常的嵌套
異常的嵌套,和if語句,函數(shù),類一樣,異常也可以嵌套,而且內(nèi)層try沒有解決的會在外層解決。
def test1():
? ? print('**********1**********')
? ? print(num)
? ? print('**********2**********')
def test2():
? ? print('**********6**********')
? ? test1()
? ? print('**********7**********')
def test3():
? ? try:
? ? ? ? print('**********3**********')
? ? ? ? test1()
? ? ? ? print('**********4**********')
? ? except Exception as result:
? ? ? ? print('[Error]:%s'%result)
? ? print('**********5**********')
#test3()
test2()
如果一個異常是在一個函數(shù)中產(chǎn)生的,例如函數(shù)A---->函數(shù)B---->函數(shù)C,而異常是在函數(shù)C中產(chǎn)生的,那么如果函數(shù)C中沒有對這個異常進行處理,那么這個異常會傳遞到函數(shù)B中,如果函數(shù)B有異常處理那么就會按照函數(shù)B的處理方式進行執(zhí)行;如果函數(shù)B也沒有異常處理,那么這個異常會繼續(xù)傳遞,以此類推。。。如果所有的函數(shù)都沒有處理,那么此時就會進行異常的默認處理,即通常見到的那樣
注意觀察上圖中,當調(diào)用test3函數(shù)時,在test1函數(shù)內(nèi)部產(chǎn)生了異常,此異常被傳遞到test3函數(shù)中完成了異常處理,而當異常處理完后,并沒有返回到函數(shù)test1中進行執(zhí)行,而是在函數(shù)test3中繼續(xù)執(zhí)行。
拋出異常
拋出自定義的異常
你可以用raise語句來引發(fā)一個異常。異常/錯誤對象必須有一個名字,且它們應是Error或Exception類的子類。
classShortInputException(Exception):
? ? '''自定義的異常類'''
? ? def__init__(self, length, atleast):
? ? #super().__init__()
? ? ? ? self.length = length
? ? ? ? ?self.atleast = atleast
defmain():
? ? try:
? ? ? ? s =input('請輸入-->')
? ? ? ? ?iflen(s) <3:
? ? ? ? ? ? raiseShortInputException(len(s),3)
? ? except ShortInputExceptionasresult:
? ? ? ? print('ShortInputException: 輸入的長度是 %d,長度至少應是 %d'% (result.length, result.atleast))
? ? except Exception as result:
? ? ? ? print('[Error]:%s'%result)
? ? else:
? ? ? ? print('No Error!')
main()
異常處理中拋出異常
class Text:
? ? def __init__(self,switch):
? ? ? ? self.switch = switch
? ? def calc(self,a,b):
? ? ? ? try:
? ? ? ? ? ? print(a/b)
? ? ? ? except Exception as result:
? ? ? ? ? ? if self.switch:
? ? ? ? ? ? ? ? print("捕獲開啟,已經(jīng)捕獲到了異常,信息如下:")
? ? ? ? ? ? ? ? print(result)
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? raise
#a = Text(True)
a = Text(False)
a.calc(1,0)
python其他
==和is的使用
'''
is 是比較兩個引用是否指向了同一個對象(地址引用比較)。
== 是比較兩個對象是否相等。(比較的數(shù)值)
'''
a = 1
b = 1
print(id(a))
print(id(b))
print(a is b)
print(a == b)
a = [1,2]
b = [1,2]
print(id(a))
print(id(b))
print(a is b)
print(a == b)
深淺拷貝
'''
淺拷貝是對于一個對象的頂層拷貝
通俗的理解是:拷貝了引用,并沒有拷貝內(nèi)容
對于不變的地址不變,可變的地址變
'''
import copy
a = [11,22,33]
b = a
c = copy.copy(a)
print(a)
print(b)
print(c)
a.append(44)
print(a)
print(b)
print(c)
print(id(a))
print(id(b))
print(id(c))
print('*******************************')
'''
深拷貝是對于一個對象所有層次的拷貝(遞歸)
'''
a = [111,222,333]
b = copy.deepcopy(a)
print(a)
print(b)
print(id(a))
print(id(b))
a.append(444)
print(a)
print(b)
print(id(a))
print(id(b))
print('*******************************')
a = (11,22,33)
b = copy.copy(a)
print(id(a))
print(id(b))