1. 程式人生 > 其它 >python之部分內建函式與迭代器與異常處理

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 可迭代物件:
    迴圈語句
  1. 在執行for迴圈時,for迴圈會先將可迭代物件變為迭代器物件,也就是呼叫__iter__方法。
  2. 使用迭代器物件的__next__方法依次取值並賦值給變數名
  3. 當值取完後,自動處理報錯並退出迴圈。

前兩步的使用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

迭代取值與索引取值的區別

  • 迭代取值

    優點:相容所有的容器型別。

    缺點:無法重複取值,只能按順序取值(從左到右),取一個少一個。

  • 索引取值

    優點:可以精確反覆取值。

    缺點:只能取有序的容器型別。