Python 迭代器與生成器實例詳解
Python 迭代器與生成器實例詳解
一、如何實現(xiàn)可迭代對象和迭代器對象
1.由可迭代對象得到迭代器對象
例如l就是可迭代對象,iter(l)是迭代器對象
In [1]: l = [1,2,3,4] In [2]: l.__iter__ Out[2]: <method-wrapper '__iter__' of list object at 0x000000000426C7C8> In [3]: t = iter(l) In [4]: t.next() Out[4]: 1 In [5]: t.next() Out[5]: 2 In [6]: t.next() Out[6]: 3 In [7]: t.next() Out[7]: 4 In [8]: t.next() --------------------------------------------------------------------------- StopIteration Traceback (most recent call last) <ipython-input-8-3660e2a3d509> in <module>() ----> 1 t.next() StopIteration: for x in l: print x for 循環(huán)的工作流程,就是先有iter(l)得到一個t,然后不停的調(diào)用t.nex(),到最后捕獲到StopIteration,就結(jié)束迭代
# 下面這種直接調(diào)用函數(shù)的方法如果數(shù)據(jù)量大的時候會對網(wǎng)絡IO要求比較高,可以采用迭代器的方法
def getWeather(city): r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city='+city) data = r.json()['data']['forecast'][0] return '%s:%s,%s' %(city, data['low'], data['high']) print getWeather(u'北京') 返回值:
北京:低溫 13℃,高溫 28℃
實現(xiàn)一個迭代器對象WeatherIterator,next 方法每次返回一個城市氣溫
實現(xiàn)一個可迭代對象WeatherIterable,iter方法返回一個迭代器對象
# -*- coding:utf-8 -*- import requests from collections import Iterable, Iterator class WeatherIterator(Iterator): def __init__(self, cities): self.cities = cities self.index = 0 def getWeather(self,city): r = requests.get(u'http://wthrcdn.etouch.cn/weather_mini?city='+city) data = r.json()['data']['forecast'][0] return '%s:%s,%s' %(city, data['low'], data['high']) def next(self): if self.index == len(self.cities): raise StopIteration city = self.cities[self.index] self.index += 1 return self.getWeather(city) class WeatherIterable(Iterable): def __init__(self, cities): self.cities = cities def __iter__(self): return WeatherIterator(self.cities) for x in WeatherIterable([u'北京',u'上海',u'廣州',u'深圳']): print x.encode('utf-8') 輸出: 北京:低溫 13℃,高溫 28℃ 上海:低溫 14℃,高溫 22℃ 廣州:低溫 17℃,高溫 23℃ 深圳:低溫 18℃,高溫 24℃
二、使用生成器函數(shù)實現(xiàn)可迭代對象
1.實現(xiàn)一個可迭代對象的類,它能迭代出給定范圍內(nèi)所有素數(shù)
素數(shù)定義為在大于1的自然數(shù)中,除了1和它本身以外不再有其他因數(shù)的數(shù)稱為素數(shù)。
一個帶有 yield 的函數(shù)就是一個 generator,它和普通函數(shù)不同,生成一個 generator 看起來像函數(shù)調(diào)用,但不會執(zhí)行任何函數(shù)代碼,直到對其調(diào)用 next()(在 for 循環(huán)中會自動調(diào)用 next())才開始執(zhí)行。雖然執(zhí)行流程仍按函數(shù)的流程執(zhí)行,但每執(zhí)行到一個 yield 語句就會中斷,并返回一個迭代值,下次執(zhí)行時從 yield 的下一個語句繼續(xù)執(zhí)行。看起來就好像一個函數(shù)在正常執(zhí)行的過程中被 yield 中斷了數(shù)次,每次中斷都會通過 yield 返回當前的迭代值。
class PrimeNumbers: def __init__(self, start, end): self.start = start self.end = end def isPrimeNum(self, k): if k < 2: return False for i in xrange(2, k): if k % i == 0: return False return True def __iter__(self): for k in xrange(self.start, self.end + 1): if self.isPrimeNum(k): yield k for x in PrimeNumbers(1, 10): print x 輸出: 2 3 5 7
三、實現(xiàn)反向迭代
1.反向進行迭代
例如: 實現(xiàn)一個浮點數(shù)發(fā)生器FloatRange(和xrange類似),根據(jù)給定范圍(start, end)和步徑值(step)產(chǎn)生一系列連續(xù)浮點數(shù),如迭代FloatRange(3.0,4.0,0.2)可產(chǎn)生序列:
正向: 3.0 -> 3.2 -> 3.4 -> 3.6 -> 3.8 -> 4.0
反向: 4.0 -> 3.8 -> 3.6 -> 3.4 -> 3.2 -> 3.0
class FloatRange: def __init__(self, start, end, step=0.1): self.start = start self.end = end self.step = step def __iter__(self): t = self.start while round(t,14) <= round(self.end, 14): yield t t = t + self.step def __reversed__(self): t = self.end while round(t, 14) >= round(self.start, 14): yield t t = t - self.step for x in reversed(FloatRange(3.0, 4.0, 0.2)): print x 輸出: 4.0 3.8 3.6 3.4 3.2 3.0 for x in FloatRange(3.0, 4.0, 0.2):
print x
輸出:
3.0
3.2
3.4
3.6
3.8
4.0
上面代碼采用round函數(shù)是因為浮點數(shù)比較會有精度問題,所以需要進行四舍五入
2.對迭代器進行切片操作
例如: 有某個文本文件,想讀取其中某范圍的內(nèi)容,如100-300行之間的內(nèi)容,python中文本文件是可迭代對象,是否可以使用類似列表切片的方式得到一個100-300行文件內(nèi)容的生成器
使用標準庫中的itertools.islice,它能返回一個迭代對象切片的生成器
f = open('/var/log/dmesg') from itertools import islice # 對文件內(nèi)容100到300行之間進行切片,返回的是個生成器對象,默認歩徑是1 islice(f, 100, 300) # 前500行內(nèi)容 islice(f, 500) # 100行到末尾結(jié)束內(nèi)容 islice(f, 100, None) ps: 每次使用islice要重新申請對象,它會消耗原來的迭代對象
四、 迭代多個對象
1.在一個for語句中迭代多個可迭代對象
1、某班學生考試成績語文、數(shù)學、英語分別存儲在3個列表中,同時迭代三個列表,計算三個學生的總分(并行)
2、某年級四個班,某次考試每班英語成績分別存儲在4個列表中,依次迭代每個列表,統(tǒng)計全學年英語成績高于90分人數(shù)(串行)
解決方案:
并行: 使用內(nèi)置函數(shù)zip,它能將多個可迭代對象合并,每次迭代返回一個元組
from random import randint chinese = [randint(60,100) for _ in xrange(40)] math = [randint(60,100) for _ in xrange(40)] english = [randint(60,100) for _ in xrange(40)] total = [] for c,m,e in zip(chinese, math,english): total.append(c+m+e) print total 輸出: [204, 227, 238, 201, 227, 205, 251, 274, 210, 242, 220, 239, 237, 207, 230, 267, 263, 240, 247, 249, 255, 268, 209, 270, 259, 251, 245, 262, 234, 221, 236, 250, 251, 249, 242, 255, 232, 272, 237, 253]
串行: 使用標準庫中的itertools.chain,它能將多個可迭代對象連接
from random import randint from itertools import chain class1 = [randint(60,100) for _ in xrange(40)] class2 = [randint(60,100) for _ in xrange(42)] class3 = [randint(60,100) for _ in xrange(39)] class4 = [randint(60,100) for _ in xrange(43)] count = 0 for s in chain(class1, class2, class3, class4): if s > 90: count = count + 1 print count 輸出: 38
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
Python數(shù)據(jù)可視化之用Matplotlib繪制常用圖形
Matplotlib能夠繪制折線圖、散點圖、柱狀圖、直方圖、餅圖. 我們需要知道不同的統(tǒng)計圖的意義,以此來決定選擇哪種統(tǒng)計圖來呈現(xiàn)我們的數(shù)據(jù),今天就帶大家詳細了解如何繪制這些常用圖形,需要的朋友可以參考下2021-06-06教你用Python實現(xiàn)簡易版學生信息管理系統(tǒng)(含源碼)
學生管理信息系統(tǒng)主要用來日常查詢學生信息,以及及時更新數(shù)據(jù)和修改數(shù)據(jù).用python實現(xiàn)簡單學生管理信息系統(tǒng)不僅可以滿足以上要求,也可以鞏固之前學習的基礎,需要的朋友可以參考下2021-06-06探索Python元類與class語句協(xié)議掌握類的控制權(quán)
這篇文章主要介紹了通過Python元類與class語句協(xié)議掌握類的控制權(quán)探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01詳談pandas中agg函數(shù)和apply函數(shù)的區(qū)別
下面小編就為大家分享一篇詳談pandas中agg函數(shù)和apply函數(shù)的區(qū)別,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04Python代碼顯得Pythonic(區(qū)別于其他語言的寫法)
這篇文章主要介紹了Python代碼顯得Pythonic(區(qū)別于其他語言的寫法),對于字符串連接,相比于簡單的+,更pythonic的做法是盡量使用%操作符或者format函數(shù)格式化字符串,感興趣的小伙伴和小編一起進入文章了解更詳細相關(guān)知識內(nèi)容吧2022-02-02python爬蟲實戰(zhàn)steam加密逆向RSA登錄解析
今天帶來爬蟲實戰(zhàn)的文章。在挑選游戲的過程中感受學習,讓你突飛猛進。本文主要實現(xiàn)用Python逆向登錄世界上最大的游戲平臺源碼分享,了解steam加密手段有多高明2021-10-10PyInstaller將Python文件打包為exe后如何反編譯(破解源碼)以及防止反編譯
這篇文章主要介紹了PyInstaller將Python文件打包為exe后如何反編譯(破解源碼)以及防止反編譯,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04