Python中生成器和迭代器的區(qū)別詳解
Python中生成器和迭代器的區(qū)別(代碼在Python3.5下測試):
Num01–>迭代器
定義:
對于list、string、tuple、dict等這些容器對象,使用for循環(huán)遍歷是很方便的。在后臺for語句對容器對象調(diào)用iter()
函數(shù)。iter()
是python內(nèi)置函數(shù)。
iter()
函數(shù)會返回一個定義了next()
方法的迭代器對象,它在容器中逐個訪問容器內(nèi)的元素。next()
也是python內(nèi)置函數(shù)。在沒有后續(xù)元素時,next()
會拋出一個StopIteration異常,通知for語句循環(huán)結(jié)束。
迭代器是用來幫助我們記錄每次迭代訪問到的位置,當(dāng)我們對迭代器使用next()函數(shù)的時候,迭代器會向我們返回它所記錄位置的下一個位置的數(shù)據(jù)。實際上,在使用next()
函數(shù)的時候,調(diào)用的就是迭代器對象的_next_方法(Python3中是對象的_next_方法,Python2中是對象的next()
方法)。所以,我們要想構(gòu)造一個迭代器,就要實現(xiàn)它的_next_方法。但這還不夠,python要求迭代器本身也是可迭代的,所以我們還要為迭代器實現(xiàn)_iter_方法,而_iter_方法要返回一個迭代器,迭代器自身正是一個迭代器,所以迭代器的_iter_方法返回自身self即可。
一些術(shù)語的解釋:
1,迭代器協(xié)議:對象需要提供next()
方法,它要么返回迭代中的下一項,要么就引起一個StopIteration異常,以終止迭代。
2,可迭代對象:實現(xiàn)了迭代器協(xié)議對象。list、tuple、dict都是Iterable(可迭代對象),但不是Iterator(迭代器對象)。但可以使用內(nèi)建函數(shù)iter()
,把這些都變成Iterable(可迭代器對象)。
3,for item in Iterable 循環(huán)的本質(zhì)就是先通過iter()
函數(shù)獲取可迭代對象Iterable的迭代器,然后對獲取到的迭代器不斷調(diào)用next()
方法來獲取下一個值并將其賦值給item,當(dāng)遇到StopIteration的異常后循環(huán)結(jié)束
Python自帶容器對象案例:
# 隨便定義一個list listArray=[1,2,3] # 使用iter()函數(shù) iterName=iter(listArray) print(iterName) # 結(jié)果如下:是一個列表list的迭代器 # <list_iterator object at 0x0000017B0D984278> print(next(iterName)) print(next(iterName)) print(next(iterName)) print(next(iterName))#沒有迭代到下一個元素,直接拋出異常 # 1 # 2 # 3 # Traceback (most recent call last): # File "Test07.py", line 32, in <module> # StopIteration
Python中一個實現(xiàn)了_iter_方法和_next_方法的類對象,就是迭代器,如下案例是計算菲波那切數(shù)列的案例
class Fib(object): def __init__(self, max): super(Fib, self).__init__() self.max = max def __iter__(self): self.a = 0 self.b = 1 return self def __next__(self): fib = self.a if fib > self.max: raise StopIteration self.a, self.b = self.b, self.a + self.b return fib # 定義一個main函數(shù),循環(huán)遍歷每一個菲波那切數(shù) def main(): # 20以內(nèi)的數(shù) fib = Fib(20) for i in fib: print(i) # 測試 if __name__ == '__main__': main()
解釋說明:
在本類的實現(xiàn)中,定義了一個_iter_(self)
方法,這個方法是在for循環(huán)遍歷時被iter()調(diào)用,返回一個迭代器。因為在遍歷的時候,是直接調(diào)用的python內(nèi)置函數(shù)iter()
,由iter()通過調(diào)用_iter_(self)
獲得對象的迭代器。有了迭代器,就可以逐個遍歷元素了。而逐個遍歷的時候,也是使用內(nèi)置的next()函數(shù)通過調(diào)用對象的_next_(self)
方法對迭代器對象進行遍歷。所以要實現(xiàn)_iter_(self)
和_next_(self)
這兩個方法。
而且因為實現(xiàn)了_next_(self)
方法,所以在實現(xiàn)_iter_(self)
的時候,直接返回self就可以。
總結(jié)一句話就是:
在循環(huán)遍歷自定義容器對象時,會使用python內(nèi)置函數(shù)iter()
調(diào)用遍歷對象的_iter_(self)
獲得一個迭代器,之后再循環(huán)對這個迭代器使用next()
調(diào)用迭代器對象的_next_(self)
。
注意點: _iter_(self)
只會被調(diào)用一次,而_next_(self)
會被調(diào)用 n 次,直到出現(xiàn)StopIteration異常。
Num02–>生成器
作用:
>延遲操作。也就是在需要的時候才產(chǎn)生結(jié)果,不是立即產(chǎn)生結(jié)果。
注意事項:
>生成器是只能遍歷一次的。
>生成器是一類特殊的迭代器。
分類:
第一類:生成器函數(shù):還是使用 def 定義函數(shù),但是,使用yield而不是return語句返回結(jié)果。yield語句一次返回一個結(jié)果,在每個結(jié)果中間,掛起函數(shù)的狀態(tài),以便下次從它離開的地方繼續(xù)執(zhí)行。
如下案例加以說明:
# 菲波那切數(shù)列 def Fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1 return '親!沒有數(shù)據(jù)了...' # 調(diào)用方法,生成出10個數(shù)來 f=Fib(10) # 使用一個循環(huán)捕獲最后return 返回的值,保存在異常StopIteration的value中 while True: try: x=next(f) print("f:",x) except StopIteration as e: print("生成器最后的返回值是:",e.value) break
第二類:生成器表達式:類似于列表推導(dǎo),只不過是把一對大括號[]
變換為一對小括號()
。但是,生成器表達式是按需產(chǎn)生一個生成器結(jié)果對象,要想拿到每一個元素,就需要循環(huán)遍歷。
如下案例加以說明:
# 一個列表 xiaoke=[2,3,4,5] # 生成器generator,類似于list,但是是把[]改為() gen=(a for a in xiaoke) for i in gen: print(i) #結(jié)果是: 2 3 4 5 # 為什么要使用生成器?因為效率。 # 使用生成器表達式取代列表推導(dǎo)式可以同時節(jié)省 cpu 和 內(nèi)存(RAM)。 # 如果你構(gòu)造一個列表(list)的目的僅僅是傳遞給別的函數(shù), # 比如 傳遞給tuple()或者set(), 那就用生成器表達式替代吧! # 本案例是直接把列表轉(zhuǎn)化為元組 kk=tuple(a for a in xiaoke) print(kk) #結(jié)果是: (2, 3, 4, 5) # python內(nèi)置的一些函數(shù),可以識別這是生成器表達式,外面有一對小括號,就是生成器 result1=sum(a for a in range(3)) print(result1) # 列表推導(dǎo)式 result2=sum([a for a in range(3)]) print(result2)
總結(jié)
以上就是本文關(guān)于Python中生成器和迭代器的區(qū)別詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關(guān)文章
Python+Pygame實戰(zhàn)之詩詞填空游戲的實現(xiàn)
成語接龍大家都玩過,但詩詞填空大家玩過嗎?把成語接龍變成填空題。難度可上漲了不止一個檔次呢!本文就來用Python和Pygame實現(xiàn)詩詞填空游戲,需要的可以參考一下2022-12-12python使用datetime模塊處理日期時間及常用功能詳解
datetime模塊是Python標準庫中用于處理日期和時間的模塊,在本節(jié)中,我們將介紹datetime模塊的一些常用功能,并通過實例代碼詳細講解每個知識點,有需要的朋友可以借鑒參考下,希望能夠有所幫助2023-06-06在python3.64中安裝pyinstaller庫的方法步驟
這篇文章主要介紹了在python3.64中安裝pyinstaller庫的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06pycocotools介紹以及在windows10下的安裝過程
這篇文章主要介紹了pycocotools介紹以及在windows10下的安裝過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-02-02Python 實現(xiàn)隨機數(shù)詳解及實例代碼
這篇文章主要介紹了Python 實現(xiàn)隨機數(shù)詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下2017-04-04