亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Python > 正文

深入講解Python中的迭代器和生成器

2020-01-04 17:58:23
字體:
來源:轉載
供稿:網友

這篇文章主要介紹了Python中的迭代器和生成器,涉及到Python中很多重要的特性,需要的朋友可以參考下

在Python中,很多對象都是可以通過for語句來直接遍歷的,例如list、string、dict等等,這些對象都可以被稱為可迭代對象。至于說哪些對象是可以被迭代訪問的,就要了解一下迭代器相關的知識了。

迭代器

迭代器對象要求支持迭代器協議的對象,在Python中,支持迭代器協議就是實現對象的__iter__()和next()方法。其中__iter__()方法返回迭代器對象本身;next()方法返回容器的下一個元素,在結尾時引發StopIteration異常。

__iter__()和next()方法

這兩個方法是迭代器最基本的方法,一個用來獲得迭代器對象,一個用來獲取容器中的下一個元素。

對于可迭代對象,可以使用內建函數iter()來獲取它的迭代器對象:

深入講解Python中的迭代器和生成器

例子中,通過iter()方法獲得了list的迭代器對象,然后就可以通過next()方法來訪問list中的元素了。當容器中沒有可訪問的元素后,next()方法將會拋出一個StopIteration異常終止迭代器。

其實,當我們使用for語句的時候,for語句就會自動的通過__iter__()方法來獲得迭代器對象,并且通過next()方法來獲取下一個元素。

自定義迭代器

了解了迭代器協議之后,就可以自定義迭代器了。

下面例子中實現了一個MyRange的類型,這個類型中實現了__iter__()方法,通過這個方法返回對象本身作為迭代器對象;同時,實現了next()方法用來獲取容器中的下一個元素,當沒有可訪問元素后,就拋出StopIteration異常。

 

 
  1. class MyRange(object): 
  2. def __init__(self, n): 
  3. self.idx = 0 
  4. self.n = n 
  5.  
  6. def __iter__(self): 
  7. return self 
  8.  
  9. def next(self): 
  10. if self.idx < self.n: 
  11. val = self.idx 
  12. self.idx += 1 
  13. return val 
  14. else
  15. raise StopIteration() 
  16.  
  17. class MyRange(object): 
  18. def __init__(self, n): 
  19. self.idx = 0 
  20. self.n = n 
  21.  
  22. def __iter__(self): 
  23. return self 
  24.  
  25. def next(self): 
  26. if self.idx < self.n: 
  27. val = self.idx 
  28. self.idx += 1 
  29. return val 
  30. else
  31. raise StopIteration() 

這個自定義類型跟內建函數xrange很類似,看一下運行結果:

 

 
  1. myRange = MyRange(3) 
  2. for i in myRange: 
  3. print i 

深入講解Python中的迭代器和生成器

迭代器和可迭代對象

在上面的例子中,myRange這個對象就是一個可迭代對象,同時它本身也是一個迭代器對象。

看下面的代碼,對于一個可迭代對象,如果它本身又是一個迭代器對象,就會有下面的 問題,就沒有辦法支持多次迭代。

深入講解Python中的迭代器和生成器

為了解決上面的問題,可以分別定義可迭代類型對象和迭代器類型對象;然后可迭代類型對象的__iter__()方法可以獲得一個迭代器類型的對象??聪旅娴膶崿F:

 

 
  1. class Zrange: 
  2. def __init__(self, n): 
  3. self.n = n 
  4.  
  5. def __iter__(self): 
  6. return ZrangeIterator(self.n) 
  7.  
  8. class ZrangeIterator: 
  9. def __init__(self, n): 
  10. self.i = 0 
  11. self.n = n 
  12.  
  13. def __iter__(self): 
  14. return self 
  15.  
  16. def next(self): 
  17. if self.i < self.n: 
  18. i = self.i 
  19. self.i += 1 
  20. return i 
  21. else
  22. raise StopIteration()  
  23.  
  24. zrange = Zrange(3) 
  25. print zrange is iter(zrange)  
  26.  
  27. print [i for i in zrange] 
  28. print [i for i in zrange] 

代碼的運行結果為:

深入講解Python中的迭代器和生成器

其實,通過下面代碼可以看出,list類型也是按照上面的方式,list本身是一個可迭代對象,通過iter()方法可以獲得list的迭代器對象:

深入講解Python中的迭代器和生成器

生成器

在Python中,使用生成器可以很方便的支持迭代器協議。生成器通過生成器函數產生,生成器函數可以通過常規的def語句來定義,但是不用return返回,而是用yield一次返回一個結果,在每個結果之間掛起和繼續它們的狀態,來自動實現迭代協議。

也就是說,yield是一個語法糖,內部實現支持了迭代器協議,同時yield內部是一個狀態機,維護著掛起和繼續的狀態。

下面看看生成器的使用:

深入講解Python中的迭代器和生成器

在這個例子中,定義了一個生成器函數,函數返回一個生成器對象,然后就可以通過for語句進行迭代訪問了。

其實,生成器函數返回生成器的迭代器。 “生成器的迭代器”這個術語通常被稱作”生成器”。要注意的是生成器就是一類特殊的迭代器。作為一個迭代器,生成器必須要定義一些方法,其中一個就是next()。如同迭代器一樣,我們可以使用next()函數來獲取下一個值。

生成器執行流程

下面就仔細看看生成器是怎么工作的。

從上面的例子也可以看到,生成器函數跟普通的函數是有很大差別的。

結合上面的例子我們加入一些打印信息,進一步看看生成器的執行流程:

深入講解Python中的迭代器和生成器

通過結果可以看到:

當調用生成器函數的時候,函數只是返回了一個生成器對象,并沒有 執行。

當next()方法第一次被調用的時候,生成器函數才開始執行,執行到yield語句處停止

next()方法的返回值就是yield語句處的參數(yielded value)

當繼續調用next()方法的時候,函數將接著上一次停止的yield語句處繼續執行,并到下一個yield處停止;如果后面沒有yield就拋出StopIteration異常。

生成器表達式

在開始介紹生成器表達式之前,先看看我們比較熟悉的列表解析( List comprehensions),列表解析一般都是下面的形式。

 

 
  1. [expr for iter_var in iterable if cond_expr] 

迭代iterable里所有內容,每一次迭代后,把iterable里滿足cond_expr條件的內容放到iter_var中,再在表達式expr中應該iter_var的內容,最后用表達式的計算值生成一個列表。

例如,生成一個list來保護50以內的所以奇數:

 

 
  1. [i for i in range(50) if i%2] 

生成器表達式是在python2.4中引入的,當序列過長, 而每次只需要獲取一個元素時,應當考慮使用生成器表達式而不是列表解析。生成器表達式的語法和列表解析一樣,只不過生成器表達式是被()括起來的,而不是[],如下:

 

 
  1. (expr for iter_var in iterable if cond_expr) 

看一個例子:

深入講解Python中的迭代器和生成器

生成器表達式并不是創建一個列表, 而是返回一個生成器,這個生成器在每次計算出一個條目后,把這個條目”產生”(yield)出來。 生成器表達式使用了”惰性計算”(lazy evaluation),只有在檢索時才被賦值(evaluated),所以在列表比較長的情況下使用內存上更有效。

繼續看一個例子:

深入講解Python中的迭代器和生成器

從這個例子中可以看到,生成器表達式產生的生成器,它自身是一個可迭代對象,同時也是迭代器本身。

遞歸生成器

生成器可以向函數一樣進行遞歸使用的,下面看一個簡單的例子,對一個序列進行全排列:

 

 
  1. def permutations(li): 
  2. if len(li) == 0: 
  3. yield li 
  4. else
  5. for i in range(len(li)): 
  6. li[0], li[i] = li[i], li[0] 
  7. for item in permutations(li[1:]): 
  8. yield [li[0]] + item 
  9.  
  10. for item in permutations(range(3)): 
  11. print item 
  12.  
  13. def permutations(li): 
  14. if len(li) == 0: 
  15. yield li 
  16. else
  17. for i in range(len(li)): 
  18. li[0], li[i] = li[i], li[0] 
  19. for item in permutations(li[1:]): 
  20. yield [li[0]] + item 
  21.  
  22. for item in permutations(range(3)): 
  23. print item 

生成器的send()和close()方法

生成器中還有兩個很重要的方法:send()和close()。

send(value):

從前面了解到,next()方法可以恢復生成器狀態并繼續執行,其實send()是除next()外另一個恢復生成器的方法。

Python 2.5中,yield語句變成了yield表達式,也就是說yield可以有一個值,而這個值就是send()方法的參數,所以send(None)和next()是等效的。同樣,next()和send()的返回值都是yield語句處的參數(yielded value)

關于send()方法需要注意的是:調用send傳入非None值前,生成器必須處于掛起狀態,否則將拋出異常。也就是說,第一次調用時,要使用next()語句或send(None),因為沒有yield語句來接收這個值。

close():

這個方法用于關閉生成器,對關閉的生成器后再次調用next或send將拋出StopIteration異常。

下面看看這兩個方法的使用:

#FormatImgID_9#

總結

本文介紹了Python迭代器和生成器的相關內容。

通過實現迭代器協議對應的__iter__()和next()方法,可以自定義迭代器類型。對于可迭代對象,for語句可以通過iter()方法獲取迭代器,并且通過next()方法獲得容器的下一個元素。

像列表這種序列類型的對象,可迭代對象和迭代器對象是相互獨立存在的,在迭代的過程中各個迭代器相互獨立;但是,有的可迭代對象本身又是迭代器對象,那么迭代器就沒法獨立使用。

itertools模塊提供了一系列迭代器,能夠幫助用戶輕松地使用排列、組合、笛卡爾積或其他組合結構。

生成器是一種特殊的迭代器,內部支持了生成器協議,不需要明確定義__iter__()和next()方法。

生成器通過生成器函數產生,生成器函數可以通過常規的def語句來定義,但是不用return返回,而是用yield一次返回一個結果。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久久久婷婷| 国产亚洲精品一区二555| 欧美黑人性猛交| 欧美精品生活片| 欧美激情久久久久| 中文字幕亚洲欧美一区二区三区| 欧美一区二区.| 日韩性xxxx爱| 91干在线观看| 精品丝袜一区二区三区| 国产精品www| 欧美成人精品影院| 中文字幕欧美精品日韩中文字幕| 7m第一福利500精品视频| 91在线视频成人| 国产午夜精品全部视频在线播放| 97**国产露脸精品国产| 日韩免费在线观看视频| 伊人久久男人天堂| 久久av中文字幕| 91精品国产自产在线观看永久| 91久久久久久久一区二区| 91爱视频在线| 亚洲成人精品久久久| 亚洲男人天堂古典| 欧美亚洲国产视频| 一本色道久久88亚洲综合88| 伊人精品在线观看| 欧美大学生性色视频| 久久久国产在线视频| 欧美片一区二区三区| 国产一区二区三区在线观看网站| 亚洲一区国产精品| 成人黄色av播放免费| 国产乱人伦真实精品视频| 一区二区三区国产视频| 热门国产精品亚洲第一区在线| 亚洲精品一区中文字幕乱码| 97超级碰在线看视频免费在线看| 亚洲精品久久视频| 久久综合久久八八| 久久久久久成人精品| 欧美精品18videos性欧美| 色综合久久久久久中文网| 岛国av在线不卡| 亚洲a区在线视频| 日韩网站免费观看高清| 精品日本高清在线播放| 色黄久久久久久| 亚洲午夜av电影| 精品国产精品自拍| 2020欧美日韩在线视频| 国产日韩欧美电影在线观看| 久久99国产综合精品女同| 8x拔播拔播x8国产精品| 亚洲欧美日韩国产中文| 精品成人69xx.xyz| 91国在线精品国内播放| 欧美资源在线观看| 欧美激情在线观看| 久久在线免费视频| 日韩一区在线视频| 亚洲xxx自由成熟| 日韩精品小视频| 欧美精品激情blacked18| 亚洲国产中文字幕在线观看| 欧美成人免费va影院高清| 在线亚洲欧美视频| 欧美亚洲激情在线| 成人动漫网站在线观看| 成人乱色短篇合集| 一个色综合导航| 欧美洲成人男女午夜视频| 国产精品白嫩美女在线观看| 亚洲男女自偷自拍图片另类| 亚洲精品久久久久久久久久久久| 国产福利精品视频| 91国产在线精品| 日韩电影免费在线观看中文字幕| 欧美另类xxx| 国自在线精品视频| 国产精品视频久久久| 国产亚洲人成a一在线v站| 国产精品网红直播| 国产一区二区黄| 国产精品视频地址| 欧美性xxxx极品高清hd直播| 操日韩av在线电影| 在线成人免费网站| 久久精品国产亚洲精品| 美女扒开尿口让男人操亚洲视频网站| 久久久久成人精品| 亚洲三级免费看| 亚洲第一视频网站| 在线国产精品播放| 青青草一区二区| 亚洲国产三级网| 欧美日韩日本国产| 成人av在线网址| 91精品久久久久久久| 久久久久久久999| 一区二区三区四区在线观看视频| 久久九九国产精品怡红院| 久久中文字幕在线视频| 亚洲色图在线观看| 亚洲日韩中文字幕在线播放| 亚洲精品自拍偷拍| 狠狠躁夜夜躁人人爽天天天天97| 国产精品中文字幕久久久| 久久久影视精品| 欧美高跟鞋交xxxxxhd| 欧美成人在线免费| 精品欧美国产一区二区三区| 欧美一级在线播放| 成人免费大片黄在线播放| 日韩欧美国产免费播放| 欧美成人全部免费| 久久琪琪电影院| 亚洲精品欧美一区二区三区| 欧美日韩裸体免费视频| 国产日韩一区在线| 懂色aⅴ精品一区二区三区蜜月| 黑人精品xxx一区一二区| 国产亚洲精品美女| 精品国产欧美一区二区五十路| 欧美久久精品午夜青青大伊人| 日韩中文在线不卡| 中文字幕欧美日韩在线| 国产精品高潮视频| 91精品久久久久久久久久久| 97人洗澡人人免费公开视频碰碰碰| 日韩中文有码在线视频| 91精品久久久久久久久青青| 国产精品极品美女粉嫩高清在线| 精品激情国产视频| 91欧美日韩一区| 国产极品jizzhd欧美| 国产精品视频xxx| 欧美综合激情网| 日韩欧美福利视频| 精品成人在线视频| 成人欧美一区二区三区黑人孕妇| 国产精品欧美激情在线播放| 国产精品女人久久久久久| 亚洲色图激情小说| 福利视频导航一区| 欧洲一区二区视频| 亚洲成人黄色在线观看| 成人女保姆的销魂服务| 国产精品成人av性教育| 色妞色视频一区二区三区四区| 欧美香蕉大胸在线视频观看| 亚洲iv一区二区三区| 成人午夜黄色影院| 欧美日韩国产精品| 久久久噜久噜久久综合| 国产日韩精品在线播放| 久久精品青青大伊人av| 亚洲色图av在线| 精品美女国产在线| 欧美精品情趣视频| 亚洲欧洲黄色网| 欧美极品少妇xxxxⅹ免费视频| 亚洲欧美日韩中文在线制服|