python之部分內建函式與迭代器與異常處理
常見內建函式(部分)
接上一個部落格
函式 | 作用 | 用法 |
---|---|---|
help(x) | 檢視x內部的註釋 | >>> help(len) Help on built-in function len in module builtins: len(obj, /) Return the number of items in a container. |
id(x) | 獲取x的記憶體地址 | >>> id('a') 2284721012216 |
int(x) | 將x轉為整型 | >>> int('123') 123 |
str(x) | 將x轉為字串型別 | >>> str(123) '123' |
isinstance(x, y) | 判斷x是否為y型別 | >>> isinstance('a', str) True |
pow(x, y) | 返回x的y次冪 | >>> pow(2, 3) 8 |
round(x, y) | 把x四捨五入,並保留y位小數,y不寫則不要小數部分 | >>> round(2.45) 2 >>> round(2.45, 1) 2.5 |
sum(x) | 將x全部元素求和 | >>> sum([2, 4, 1]) 7 |
可迭代物件
在瞭解可迭代物件之前,我們要想了解什麼叫做迭代。
在執行重複的步驟時,每一次的結果都要依賴上一個的結果計算,這個過程就叫做迭代。
# 迭代過程
n = 0
while n < 5:
print(n)
n += 1
所以,可迭代物件其實簡單的來說就是可以放到for迴圈裡進行遍歷的資料,像列表、字典、元組、字串等等
如果在pycharm中想要檢視一個數據是否是可迭代物件,我們可以看看這個資料是否可以呼叫__iter__方法。
可以呼叫:會提示
不可以呼叫:不會提示
屬於可迭代物件的資料型別:
列表、字典、元組、集合、字串、檔案
不屬於可迭代物件的資料型別:
整型、浮點型、布林值、函式
迭代器物件
一個可迭代物件在呼叫__iter__方法後返回的結果就是迭代器物件,迭代器物件可以極大的節省儲存空間,它只會在需要用的時候才會取出資料。
迭代器物件能呼叫__iter__方法和__next__方法,所以迭代器物件一定是可迭代物件,但可迭代物件不一定是迭代器物件。
迭代器物件的取值方法
迭代器物件可以用__next__方法取值,每次可以取出一個值,取完了繼續取值會報錯。
s = 'hello'
# 將可迭代物件變為迭代器物件
res = s.__iter__()
# 呼叫__next__方法
print(res.__next__()) # 輸出:h
print(res.__next__()) # 輸出:e
print(res.__next__()) # 輸出:l
print(res.__next__()) # 輸出:l
print(res.__next__()) # 輸出:o
print(res.__next__()) # 報錯StopIteration
也可以使用next方法,等價於__next__
s = 'hello'
# 將可迭代物件變為迭代器物件
res = iter(s)
# 呼叫__next__方法
print(next(res)) # 輸出:h
print(next(res)) # 輸出:e
print(next(res)) # 輸出:l
print(next(res)) # 輸出:l
print(next(res)) # 輸出:o
print(next(res)) # 報錯StopIteration
取值注意事項
"""可迭代物件不要在呼叫__iter__的同時呼叫__next__,不然在下一次呼叫__next__還是隻會輸出第一個值"""
s = 'hello'
print(s.__iter__().__next__()) # 輸出:h
print(s.__iter__().__next__()) # 輸出:h
print(s.__iter__().__next__()) # 輸出:h
"""如果一個迭代器物件呼叫__iter__並不會有任何反應,返回的還是它本身"""
s = 'hello'
res = s.__iter__()
print(res.__iter__().__next__()) # 輸出:h
print(res.__iter__().__next__()) # 輸出:e
print(res.__next__()) # 輸出:l
for迴圈內部原理
如過此時有一串資料,我們如何不使用for迴圈將它輸出?是不是隻能使用while迴圈輸出了?
實現:
s = 'hello'
n = 0
res = iter(s)
while n < len(s):
print(next(res))
n += 1
這時候需要一個變數來判斷是否輸出完畢,而for迴圈並不需要額外的變數。
原理
首先我們要了解for迴圈的語法結構
for 變數名 in 可迭代物件:
迴圈語句
- 在執行for迴圈時,for迴圈會先將可迭代物件變為迭代器物件,也就是呼叫__iter__方法。
- 使用迭代器物件的__next__方法依次取值並賦值給變數名
- 當值取完後,自動處理報錯並退出迴圈。
前兩步的使用while迴圈表現為:
s = 'hello'
res = s.__iter__()
while True:
print(res.__next__())
第三步的報錯該怎麼處理,這就是我們接下來要學習的內容。
異常處理
異常就是報錯,報錯就說明程式碼有問題,報錯的同時程式也會立刻停止執行,異常處理就可以防止報錯時程式會停止的問題。
異常資訊的組成部分
異常資訊有三部分組成。
- Traceback部分:可以知道報錯的位置
- error部分:可以知道錯誤型別
- 報錯原因:可以知道為什麼會報錯
異常的分類
異常主要分為語法異常和邏輯異常兩大類。
- 語法異常:語法結構問題,比如if的語法結構寫錯,小白經常會犯的錯誤。
- 邏輯異常:程式碼邏輯出現問題,比如字串型別呼叫了不屬於它的方法。
異常的型別
常見錯誤型別,只列舉部分。
異常型別 | 原因 |
---|---|
NameError | 沒有宣告過的變數被使用了 |
IndexError | 沒有此索引 |
KeyError | 沒有此鍵(key) |
ValueError | 無效引數 |
ImportError | 匯入模組錯誤 |
SyntaxError | 語法錯誤 |
TypeError | 資料型別錯誤 |
IndentationError | 縮排錯誤 |
AttributeError | 呼叫了錯誤的方法 |
StopIteration | 迭代器沒有更多的值了 |
異常處理實操
對於程式碼中可能出現錯誤的程式碼,我們可以進行處理讓程式碼不會報錯,防止程式停止。
語法結構(括號內的語法可以被省略):
try:
可能會出錯的程式碼
except 錯誤型別1 (as 變數名): # 錯誤的資訊會賦值給變數名
處理措施
except 錯誤型別2 (as 變數名): # 錯誤的資訊會賦值給變數名
處理措施
...
如果不知道錯誤型別,還可以這麼寫:
try:
可能會出錯的程式碼
except Exception (as 變數名): # 錯誤的資訊會賦值給變數名
處理措施
except Exception (as 變數名): # 錯誤的資訊會賦值給變數名
處理措施
...
實操:
# 案例一:程式碼會出錯
try:
res = int('a')
print(res)
except Exception as e:
print('程式碼出錯啦')
print(e)
"""
執行結果:
程式碼出錯啦
invalid literal for int() with base 10: 'a'
"""
# 案例二:程式碼不會出錯
try:
res = int('5')
print(res)
except Exception as e:
print('程式碼出錯啦')
print(e)
"""
執行結果:
5
"""
異常處理原則:不要把全部程式碼全部寫入try中,雖然程式碼不會報錯了,但你的功能也無法實現了,異常處理只適用於檢測程式碼,能不用就不用
異常處理的其他操作
結合else使用:如果try語句裡的程式碼沒有異常,則執行else裡的程式碼。
try:
res = int('5')
print(res)
except Exception as e:
print(e)
else:
print('程式碼正常執行結束了')
"""
執行結果:
5
程式碼正常執行結束了
"""
結合finally使用:無論try語句裡的程式碼如何,最後都會執行finally裡的程式碼。
# 案例一:程式碼沒有異常
try:
res = int('5')
print(res)
except Exception as e:
print(e)
finally:
print('程式碼結束了')
"""
執行結果:
5
程式碼結束了
"""
# 案例二:程式碼有異常
try:
res = int('abc')
print(res)
except Exception as e:
print(e)
finally:
print('程式碼結束了')
"""
執行結果:
invalid literal for int() with base 10: 'abc'
程式碼結束了
"""
主動報錯:使用raise關鍵字,強行報錯,報錯原因可以自行填寫。
raise NameError('我就要報錯!!!')
# 報錯:NameError: 我就要報錯!!!
斷言(瞭解即可):使用assert關鍵字,後面跟判斷條件,條件成立則跳過,不成立就會報錯。
name = 'jason'
assert isinstance(name, str)
# 無事發生
name = 'jason'
assert isinstance(name, int)
# 報錯:AssertionError
for迴圈本質
瞭解了異常處理了現在應該明白了for迴圈的本質了吧!
# for迴圈
s = 'jason'
for i in s:
print(i)
"""利用while與異常捕獲 實現for迴圈的功能"""
s = 'jason'
# 1.先轉換成迭代器物件
res = s.__iter__()
# 2.迭代取值
while True:
# 3.異常處理
try:
print(res.__next__())
except StopIteration as e:
# 4.結束while迴圈
break
迭代取值與索引取值的區別
-
迭代取值
優點:相容所有的容器型別。
缺點:無法重複取值,只能按順序取值(從左到右),取一個少一個。
-
索引取值
優點:可以精確反覆取值。
缺點:只能取有序的容器型別。