Python學習筆記:錯誤、異常、生成器、迭代器
#錯誤&異常
程式邏輯或者語法問題產生錯誤,是一個事件
產生錯誤之後,會進入異常狀態,到呼叫函式的地方尋找解決方法,將程式恢復為正常執行狀態
異常的作用:通知上層呼叫者有錯誤發生,用作訊號通知
#try語句的try-excpetion語法
try:
可能觸發異常的語句
except 錯誤型別1 [as 變數1]:
異常處理語句
except (錯誤型別2,錯誤型別3,錯誤型別4):
異常處理語句
......
[except:
異常處理語句other
else:
未發生異常時動作
finally:
最終語句]
至少應該保留一個except
出現異常之後,接下來的程式碼將不會執行,錯誤將返回給上層呼叫者
#示例
def fenpingguo():
str1 = input("please input a num")
s = int(str1)
a = 100/s
print("over")
try:
fenpingguo()
except ValueError: #出現數值錯誤,即int()函式內部不是一個int字串
print("Error")
except ZeroDivisionError: #出現除0錯誤
print("Error2")
except (ValueError,ZeroDivisionError) as err: #出現這兩個錯誤,並且兩個錯誤元組繫結在變數Error上
print(err)
except: #如果發生了其他型別的異常
print("Error occurs")
else:
print("No error occuers") #未發生異常時執行else下方的語句塊
finally:
print("try have been excuted") #finally語句最終一定會被執行
#常用的Error
ZeroDivisionError
ValueError:傳入無效引數
AssertionError:斷言語句失敗
StopIteration:迭代器沒有更多索引值
IndexError:序列中沒有此索引
IndentationError:縮排錯誤
ImportError:匯入錯誤
NameError:未命名錯誤
IOError:輸入輸出錯誤
AttributeError:物件沒有這個屬性
BaseException:基類
SystemExit:直譯器請求退出
#try-finally用法
沒有except語句,只有
try:
xxx
finally:
xxx
無論是否產生異常,一定會執行finally下的語句;finally語句不會改變程式的執行狀態
#raise
丟擲一個錯誤,讓程式進入異常狀態
raise 異常型別
或者
raise 異常物件
比如:
def make_except():
print("function start")
myerror = ValueError("This is an ValueError")
raise myerror
print("end of function")
try:
make_except()
except ValueError:
print("Error has been dealt")
#assert 斷言語句
assert 真值表達式,資料錯誤(通常是字串)
當真值表示式為False時,用錯誤資料建立一個AssertionError型別的錯誤,並觸發此錯誤並進入異常狀態
相當於:
if 真值表達式 == False:
raise AssertionError(錯誤資料)
#迭代器 Iterator
迭代器,用於對可迭代物件做遍歷的工具
兩個相關函式
iter(iterable) 可從可迭代物件返回一個迭代器iterator
next(iterator) 從迭代器物件例項中獲取下一個記錄,如果沒有下一條記錄,則丟擲StopInteration#
示例:用迭代器遍歷一個list
for x in range(1,10,3):
print(x)
it = iter(range(1,10,3))
while True:
try:
print(next(it))
except StopIteration:
break
#生成器 Generator
生成器能夠動態的提供資料物件,生成器物件也是可迭代物件
它不像列表那種靜態可迭代物件,它是動態的
生成器函式的定義:
yield 表示式
yield僅用於def 函式中,該函式稱為生成器函式
該函式被呼叫時會生成並返回一個可迭代物件,這個物件是一個生成器物件
之後每次用next訪問該生成器函式,都會執行一遍非yield語句,然後返回下一個yield的值
生成器可以再生成一個迭代器,next(迭代器)時,會尋找生成器物件要資料,生成器會找生成器函式要資料,當生成器函式遇到一個yield時,會返回該值,然後生成器函式卡在這條yield函式之後,待下次取用,直到最後生成StopIteration異常
#練習題:寫一個myrange代替range
def myrange(stop,start = None,step = None):
if start == None:
start = 0
else:
stop,start = start,stop
if step == None:
step = 1
if step == 0:
myerror = ValueError("argv step cannot be 0")
raise myerror
if step > 0:
while start < stop:
yield start
start += step
else:
while start > stop:
yield start
start += step
it = iter(myrange(100,150,1))
try:
while True:
print(next(it))
except ValueError as err:
print("ValueError:",err)
except StopIteration as err:
print("StopIteration Error")
print("Program exit!")
#生成器函式得到的資料現用現生成,不會佔用大量記憶體空間!!!這是一個非常優越的優點
#python3中range本身就是這樣實現的
#生成器表示式
gen = (x**2 for x in List1)
it = iter(gen)
next(it)
#迭代工具函式
生成一個個性化的可迭代物件
zip(iter1,iter2,iter3,...)用多個可迭代物件,生成一個元組,元組中每個元素也是一個元組,玫每個這樣的元組即(iter1[x],iter[x],iter3[x]),x是一個確定的數,x最大是min(len(iter1),len(iter2)......)
列舉函式enumerate(iterable)
names = [1,2,3]
for x in enumerate(names):
print(x)
#練習題:輸入多個字串,列印輸入的行號和字串
l = list()
while True:
str1 = input("please input a string")
if str1 == '':
break
l.append(str1)
for x in zip(range(1,len(l)+1),l):
print("%d:%s"%(x[0],x[1]))
#練習題:用生成器函式計算斐波那契數列前n項
def fn(n):
cnt = 0
a = 1
b = 1
yield 1
cnt += 1
if cnt > n:
return
yield 1
cnt += 1
if cnt > n:
return
while True:
a,b = b,a+b
yield b
cnt += 1
if cnt > n:
return
for x in fn(20):
print(x)