python基础(part15)--迭代
鄙人學習筆記
開發工具:Spyder
文章目錄
- 迭代
- 舉個例子1
- 舉個例子2
- for循環原理
- 可迭代對象iterable
- 舉個例子1
- 舉個例子2
- 舉個例子3
- 迭代器對象iterator
- yield關鍵字迭代原理
- 舉個例子(我們將之前的MyRange類進行改寫)
迭代
每一次對過程的重復為一次”迭代”,而每一次迭代得到的結果,會作為下一次迭代的初始值。例如:循環獲取容器中的元素。
舉個例子1
創建一個列表:
再輸入以下代碼:
結果:
可以看出,我們得到的結果和for循環遍歷這個列表,得到的結果相同。
如果我們多寫一個iterator.__next__(),會怎樣呢?
結果:
會報錯 python警告我們,要 Stop Iteration, 停止迭代!
舉個例子2
還是創建原來的列表:
我們再利用以下方法迭代:
第39行代碼這樣寫,其實相當于在except之后寫了個異常基類:
結果:
我們發現,我們沒有用for循環,也拿到了可迭代對象(列表)內元素。以上兩個例子演示了for循環原理。
for循環原理
現在,我們對上面例子中的代碼進行解釋,進而闡述一下for循環原理
①獲取迭代器對象
我們說,可迭代對象,是具有__iter__()方法,可以返回迭代器的對象。所以以后我們評判一個對象是不是可迭代對象時,就可以看一看,這個對象有沒有__iter__()方法,如果有這個方法,則說明,這個對象是可以被迭代的。
②獲取下一個元素(迭代)
有迭代器之后,我們就可以迭代了,__next__()的過程就是在迭代的過程,有__next__()我們就可以拿到下一個元素。
③停止迭代(StopIteration錯誤)
最后,我們總結一下for循環原理:
①獲取迭代器對象
②循環迭代(調用迭代器的__next__()方法)
③捕獲StopIteration異常
- 小問題
問:能夠被for循環的條件是什么?
答:具有__iter__()方法的對象。
- 例子1
使用while + 迭代器,獲取元祖(“小白”, “小黃”, “大白”)中所有元素。
代碼:
t01 = ("小白", "小黃", "大白") iterator = t01.__iter__()while True:try:item = iterator.__next__()print(item)except:break結果:
- 例子2
不使用for循環,獲取字典{“小白”:0, “小黃”:6, “大白”:7}中的key和value.
代碼:
d01 = {"小白":0, "小黃":6, "大白":7}iterator = d01.__iter__()while True:try:key = iterator.__next__()print(key, d01[key])except:break結果:
備注:使用迭代器迭代字典,拿到的是字典的key
可迭代對象iterable
- 定義
具有__iter__()函數的對象,可以返回迭代器對象.
- 語法
創建可迭代對象:
class 可迭代對象名稱:def __iter__(self):return 迭代器使用可迭代對象:
for 變量名 in 可迭代對象:語句- 原理
舉個例子1
首先創建兩個類:
再創建SkillManager對象,并試著迭代此對象的成員變量skills:
得到結果:
結果得到了列表內的各個Skill對象。
但是,如果我們只迭代SkillManager對象會怎樣呢?我們看看下面這個例子。
舉個例子2
利用例子1,創建的兩個類:
再創建SkillManager對象,并試著迭代此對象:
運行:
報錯!且python提示我們SkillManager對象是個不可迭代的對象。
接下來,我們就要讓SkillManager可迭代!
我們先要在SkillManager類里增加一個__iter__()方法,使他變為可迭代對象。 這個__iter__()被調用后,應該返回一個迭代器類對象SkillIterator。這個迭代器類對象里應該有一個__next__()方法,用于返回下一個元素。在__next__()方法里應該拋出一個索引越界異常,當被迭代對象全部迭代完后,再獲取下一個元素,則會拋出異常。具體情況,我們看看下面的代碼。
現在我們看一下SkillManager類:
再看一下SkillIterator類:
創建對象,并開始利用for循環原理,進行迭代:
我們再運行一下,看一下運行結果:
不錯!可迭代對象內元素全部拿到了。
備注1:由上面的過程我們也可以看出,可迭代對象不會直接return它的元素,而是由迭代器return了可迭代對象內的元素。
備注2:若我們用for循環,則它也會先獲取迭代器對象,獲取完迭代器對象后,再用迭代器對象不斷的調用__next__()方法,直到迭代器對象拋出異常,for再進行異常處理。
舉個例子3
參照下例代碼,定義MyRange類,實現相同效果:
代碼:
結果:
備注:誰要被for,誰要就有__iter__()方法,這個方法可以獲取迭代器,迭代器內部具體怎么寫?看需求!迭代器中有__next__(),可以返回下一個元素。
迭代器對象iterator
- 定義
可以調用__next__()函數,并返回下一個值得對象。
- 語法
- 說明
聚合對象通常是容器對象。
- 作用
使用者只通過一種方式(for循環),便可以簡潔明了獲取聚合對象中的各個元素,而又無需了解可迭代對象的內部存儲結構。
==備注!==若我們在__iter__()方法內不返回自己創建的迭代器對象,而用yield關鍵字自動生成迭代器對象,會怎樣呢?
請看以下案例
代碼:
結果:
執行過程:
①客戶端調用__iter__()方法,__iter__()方法不執行, 進入while循環.
②客戶端調用__next__()方法,__iter__()方法執行,先執行print("準備返回第一個元素"), 執行到yield語句, 將yield后的數據作為__next__()方法的返回值return給item, 并且暫時離開__iter__()方法, 繼續執行while循環中的print(item).
③當再次調用__next__()方法時,從上次離開的代碼開始執行,再運行到下一個yield語句,return數據之后,并再次暫時離開.
④待執行完__iter__()方法體,若再次調用__next__()方法,會自動拋出StopIteration異常.
yield關鍵字迭代原理
- 原理
如果方法體中包含yield關鍵字,那么會自動生成迭代器對象.
生成迭代器代碼的大致規則:
①將yield關鍵字前的代碼,放到__next__()方法中.
②將yield關鍵字后的數據,作為__next__()方法的返回值.
舉個例子(我們將之前的MyRange類進行改寫)
代碼:
結果:
若我們不定義類,而只定義包含yield的方法,來滿足我們迭代的需求,該怎么做呢?
代碼:
結果:
我們說這項技術,就叫做生成器generator函數.
總結
以上是生活随笔為你收集整理的python基础(part15)--迭代的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 赵州桥的主要特点
- 下一篇: python基础(part16)--生成