1. 程式人生 > 其它 >2022.3.23學習筆記

2022.3.23學習筆記

2022.3.23學習筆記

  • 可迭代物件
  • 迭代器物件
  • for迴圈的內部原理
  • 異常處理
  • for迴圈的本質(程式碼模擬)
  • 迭代取值與索引取值的對比

一、可迭代物件

1、迭代的概念

迭代就是更新換代,每一次迭代都是基於上一次的結果,類似遊戲版本的更新

特徵:每一次的結果都不一樣或者都有更新才叫做迭代

while True:
    print(123)  # 單純的迴圈不叫迭代

n = 1
while True:
    print(n)
    n +=1  # 每次都不一樣的,這樣的迴圈才屬於迭代
    
# 迭代取值
l1 = [11, 22, 33, 44, 55]
n = 0
while n < len(l1):
    print(len(n))
    n += 1

2、可迭代物件

內建有__iter__方法的都可成為可迭代物件,一般支援for迴圈的都是可迭代物件,如字串、列表、字典、元組、集合、檔案物件等

# 可迭代物件可以用.__iter__的方式進行呼叫
# __iter__讀法:雙下iter方法,不要讀槓槓
s = 'jsdon'
s.__iter__

二、迭代器物件

1、概念

可迭代物件呼叫__iter__方法後生成的結果就是迭代器物件

2、特徵

含有__iter__()方法和__next__()方法
s = 'jsdon'
res = s.__iter__()  # 將s轉為迭代器物件
res.__next__()  # 使用next呼叫res這個迭代器物件,表示取第一個元素

3、迭代器物件的理解

作用:極大節省儲存空間

類似哆啦a夢的口袋,不用的時候就是一個口袋,用的時候可以拿出很多東西

4、迭代器物件如何取值

呼叫__next__()方法即可
注意:如果資料取完了則會直接報錯!!!
# for迴圈的底層依據就是迭代器物件

5、迭代器物件補充說明

(1)轉化及呼叫的簡易寫法

__iter__() == iter()

__next__() == next()

(2)檔案物件

檔案物件本身就是迭代器物件,無須使用iter()呼叫

(3)多次呼叫iter()的結果

可迭代物件呼叫1次iter()會轉化成迭代器物件,如果繼續呼叫結果還是迭代器物件本身

res = s.__iter__()
res1 = s.__iter__().__iter__().__iter__()
res == res1  # 兩個迭代器物件是一樣的

(4)迭代取值的要求

s = 'jason'
print(s.__iter__().__next__())  # j
print(s.__iter__().__next__())  # j
print(s.__iter__().__next__())  # j
print(s.__iter__().__next__())  # j
print(s.__iter__().__next__())  # j

思考?為什麼以上呼叫了5次結果一樣呢?

這是因為s轉化成迭代器物件之後需要一個變數名接收,不然再次呼叫還是從頭開始的,因此要這樣使用

s = 'jason'
res = s.__iter__()
print(res.__next__())  # j
print(res.__next__())  # a
print(res.__next__())  # s
print(res.__next__())  # o
print(res.__next__())  # n

三、for迴圈內部原理

先看for迴圈的結構:

for 變數名 in 可迭代物件:

​ 迴圈體程式碼

經過之前的學習,in後面相當於是將可迭代物件iter()一下變成迭代器物件,然後迴圈取裡面的值,直到取完

l1 = [1, 2, 3, 4, 5, 6, 7]
res = l1.__iter__()
n = 0
while n < len(l1):
    print(res.__next__())
    n +=1  # 這裡如果不進行人為計數,就會出現異常,也就是報錯

所以什麼是異常處理呢?

四、異常處理

1、什麼是異常

程式碼執行出錯之後就是異常,異常會導致程式立刻停止,因此我們再編寫程式碼的時候需要極力避免(異常的外號叫:bug)

2、異常資訊的組成部分(報錯)

先看下面這個報錯資訊

1.Traceback (most recent call last):
2.  File "/Users/jiboyuan/PycharmProjects/day16/05 異常處理.py", line 3, in <module>
    name
3.NameError: name 'name' is not defined

序號1:line關鍵字所在的一行,用於提示哪一行報錯,點選藍色字型即可定位,如果報錯資訊很長,那麼一般最後一個才是

序號2:NameError是錯誤的型別中的一種,還有很多其他型別

序號3:name 'name' is not defined是具體的報錯原因,一般也是解決報錯的方法

3、異常的分類

1.語法異常

最基礎的語法結構,出現了會立即報錯,pycharm中會出現紅色波浪線

2.邏輯異常

不會直接報錯,語法裡有這個操作,但是亂用,比如:

name = 'jason'
name.append()  # 不會立馬報錯,但是字串不可以使用列表內建方法,執行程式便會報錯

如果邏輯異常,儘快修改即可

4、異常型別

舉幾個例子,如下

1.print(name)  # NameError 名字錯誤
2.l1 = [1, 2, 3]
print(l1[100])  # IndexError 索引錯誤
3.dict = {'name':'jason'}
print(dict['age'])  # KeyError 鍵錯誤
4.int('jason')  # ValueError 值錯誤
......

還有很多異常的型別,需要再改bug的時候多熟悉

五、異常處理實操

1、基本語法結構

try:
    可能會出錯的程式碼
except 錯誤型別1 as e: # e指代錯誤提示資訊
	針對1的處理措施
except 錯誤型別2 as e:
	針對2的處理措施
except 錯誤型別3 as e:
	針對3的處理措施
...

2、統一錯誤型別處理

由於有時候自己也不清楚是什麼bug,使用下面的語法結構,可以對任意錯誤型別進行操作,也叫“萬能異常”

try:
    可能會出錯的程式碼
except Exception as e:
    統一的額處理措施

但是並不是以後都可以用這種方式,因為異常處理的準則就是被檢測的程式碼越少越好,儘量少用

3、異常處理了解篇

(1)結合else使用

try檢測的程式碼沒有發生異常,正常執行完畢後會執行else的子程式碼

try:  # 檢測程式碼有無異常
    可能會出錯的程式碼
except Exception as e:  # 檢測異常走except子程式碼  
    統一的處理措施
else:  # 檢測無異常走else子程式碼
    可能會出錯的程式碼沒有出錯 最後走else子程式碼

(2)結合finally使用

無論try檢測的程式碼有無異常最後都會執行finally子程式碼

try:  # 檢測程式碼有無異常
    可能會出錯的程式碼
except Exception as e:  # 檢測異常走except子程式碼  
    統一的處理措施
else:  # 檢測無異常走else子程式碼
    可能會出錯的程式碼沒有出錯 最後走else子程式碼
finally:  ####### 最後一步都會走finally
    無論上面有沒有異常,最後都會走這一步

(3)assert斷言

name = 'jaosn'
assert isinstance(name,str) 

(4)raise主動報錯(需要掌握)

raise NameError('就是要報錯,怎麼了')
因為是主動報錯,所以明確知道是什麼錯誤

六、for迴圈的本質

瞭解了異常處理的一些知識,我們再回到for迴圈的原理上

l1 = [1, 2, 3, 4, 5, 6, 7]
res = l1.__iter__()
n = 0
while n < len(l1):
    print(res.__next__())
    n +=1  # 這裡如果不進行人為計數,就會出現異常,也就是報錯

剛才說了,這裡如果不寫n += 1,資料取完後就會報錯,結合異常處理的知識我們可以這樣做:

l1 = [1, 2, 3, 4, 5, 6, 7]
res = l1.__iter__()
while True:
    try:
        print(res.__next__())  # 檢測這一行程式碼
    except StopIteration as e:  # 執行時瞭解到報錯StopIteration
        break  # 報錯直接退出迴圈

這樣在我們知道報錯的型別就可以加以相應的處理措施啦,是不是很神奇

七、迭代取值與索引取值的對比

1、索引取值

優勢:可以反覆取相同元素,沒有固定方向

劣勢:只能支援有序的容器型別,且相容性沒有迭代取值高

2、迭代取值

優勢:相容所有容器型別

劣勢:永遠是順序取值,且無法重複獲取,取完就結束

注意:迭代器裡面的東西,取一個少一個,取完就沒了