迭代器跟生成器,與上篇文章講的裝飾器同樣,都是屬於個人一個老大難問題。
一般就是遇到的時候就去搜一下,結果在一大坨各類介紹博客中看了看,回頭又忘記了。
你是否是也是這樣呢?python
俗話說:好記性不如爛筆頭,雖然如今基本不咋用筆寫字了,可是仍是要好好整理下,起碼之後我就不用搜了。數據結構
若是如今給你一個列表list_a = [1, 2, 3, 4]
,讓你去迭代它,相信你們都很熟悉,直接用for循環就完事兒,函數
list_a = [1, 2, 3, 4] for i in list_a: print(i)
運行測試
1 2 3 4 [Finished in 0.1s]
能夠看到,for循環迭代了列表中的每個元素,打印了出來。
那麼for循環背後都作了什麼事情呢?code
聽起來陌生,可是你絕對熟悉的詞兒。對象
在python中,一切都是對象,對象的抽象是類,而對象的集合就是容器。內存
使用python中常見的容器有不少,好比:列表list:[0, 1, 2]
,集合set:([0, 1, 2])
,字典dict:{0:0, 1:1, 2:2}
以及元組tuple(0, 1, 2)
。
這些都是多個元素集中在一塊兒的單元,區別的是內部數據結構的實現方法。generator
全部的容器都是能夠迭代的,你能夠用for循環去迭代上述的容器試試。博客
那把一個個元素找出來,用到的就是迭代器。用iter()能夠建立一個迭代器。it
迭代器提供一個next()
方法,這個方法你每次調用的時候會給你返回下一個對象,或者StopIteration
,也就是沒有對象能夠給你了。
list_a = [1, 2, 3, 4] it = iter(list_a) # 建立迭代器 print(next(it)) #調用next() print(next(it)) print(next(it)) print(next(it)) print(next(it))
運行結果,前4個print能夠正常返回,第5個時候就出現StopIteration
錯誤了,由於列表中4個元素已經返回完了。
1 2 3 4 Traceback (most recent call last): File "D:\練習\demo_iterator.py", line 9, in <module> print(next(it)) StopIteration [Finished in 0.1s with exit code 1]
什麼是生成器?簡單粗暴一點:生成器就是懶人版的迭代器。
在上述的建立迭代器操做中,咱們顯然是作了一次性生成的操做,list_a = [1, 2, 3, 4]
,這4個元素一次性生成好,以供next()
調用。
可是生成出的這些元素都是會保存到內存中去,這只是4個元素,若是有上千萬、上億元素呢?
我並非第一時間要用到全部的元素,我只要在我調用next()
的時候產生一個返回給我就好,那麼這樣一次性生成就會白白佔用了大量的內存。
生成器應運而生,當調用next()
的時候,纔會生成下一個變量。
生成器的寫法很簡單,用小括號,好比把一個列表生成式括起來:(i for i in range(10000))
,這樣就初始化了一個生成器。
print([i for i in range(10)]) print(i for i in range(10))
上面的時列表,下面的就是一個生成器了,區別就是[]
和()
。
運行結果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <generator object <genexpr> at 0x033383A8> [Finished in 0.1s]
此外,函數也能夠成爲生成器,祕密就是yield
關鍵字,好比:
def gen(): a = 0 while a < 100: yield a a += 1 test = gen() print(next(test)) print(next(test)) print(next(test)) print(next(test))
運行結果:
0 1 2 3 [Finished in 0.1s]
yield
關鍵字,能夠這樣理解:當函數運行到這一行的時候,程序會從這裏暫停,yield
至關於return
會返回,
當下次迭代時候,則會從yield
的下一行代碼開始執行。
因此,我調用了4次print,能夠從0開始依次輸出。
從我工做中的使用場景出發的話,我在作一些自動化測試的時候,有些變量參數是不能夠重複的,用迭代器來定義變量的生成規則,每次 調用都會產生一個新的,就不會重複了。