Iterator(迭代器)
-
概念
迭代器是訪問集合元素的一種方式勿璃。迭代器對象從集合的第一個元素開始訪問扎酷,直到所有的元素被訪問完結(jié)束。迭代器只能往前不會后退颈畸。
-
可迭代對象
迭代器提供了一個統(tǒng)一的訪問集合的接口伞访。只要是實現(xiàn)了iter()或getitem()方法的對象掂骏,就可以使用迭代器進行訪問轰驳。
例子:
- 序列:字符串厚掷、列表、元組
- 非序列:字典级解、文件
- 自定義類:用戶自定義的類實現(xiàn)了iter()或getitem()方法的對象
-
可迭代對象創(chuàng)建的兩種方法
第一種:
# 迭代器對象實現(xiàn)了__iter__()方法 class Fibs: def __init__(self): self.a = 0 self.b = 0 def next(self): self.a,self.b = self.b,self.a+self.b return self.a def __iter__(self): return self
__iter__
()方法實現(xiàn)了對象可迭代冒黑,next()方法實現(xiàn)了迭代。第二種:
# 用iter()工廠類實例化一個可迭代對象 it = iter([1,2,3]) it.next()
-
從迭代器中獲得序列
it = iter([1,23,3]) lits(it)
使用list構(gòu)造方法顯式地講迭代器轉(zhuǎn)化成列表勤哗。
-
一種更方便的建立迭代器
# 用括號擴住才是迭代器 it = (x for x in [2,3,4])
生成器
概念
生成器是一種用普通的函數(shù)語法定義的迭代器(也叫簡單生成器)抡爹,有點像java中的靜態(tài)域里面的數(shù)據(jù),但用更加靈活芒划。生成器不會把結(jié)果保存在一個系列中冬竟,而是保存生成器的狀態(tài),在每次進行迭代時返回一個值民逼,直到遇到StopIteration異常結(jié)束泵殴。-
yield
在函數(shù)中如果出現(xiàn)了yield關(guān)鍵字,那么該函數(shù)就不再是普通函數(shù)拼苍,而是生成器函數(shù)笑诅。
yield 的作用就是把一個函數(shù)變成一個 generator,帶有 yield 的函數(shù)不再是一個普通函數(shù),Python 解釋器會將其視為一個 generator吆你∠乙叮可以用for循環(huán)遍歷相比于迭代器,生成器更加靈活妇多。
程序執(zhí)行到y(tǒng)ield后就會返回輸出伤哺,yield下面的代碼會在下次調(diào)用next()時運行
-
yield與return
在一個生成器中,如果沒有return默责,則默認執(zhí)行到函數(shù)完畢時返回StopIteration
如果遇到return,如果在執(zhí)行過程中 return,則直接拋出 StopIteration 終止迭代桃序。# 不會執(zhí)行到'b' def ge(): yield 'a' return yield 'b'
如果在return后返回一個值烂瘫,那么這個值為StopIteration異常的說明媒熊,不是程序的返回值。
# 不會輸出'world' def ge(): yield 'hello' return 'world'
?
-
創(chuàng)建一個生成器
-
簡單生成器
# 簡單生成器坟比,一個無窮產(chǎn)生奇數(shù)的生成器函數(shù) def odd(): n=1 while True: yield n n+=2
-
循環(huán)生成器
# 循環(huán)生成器 g = ((i+2)**2 for i in range(2, 27))
range()是一個生成器
遞歸生成器
# 處理多層嵌套的數(shù)據(jù)(二維數(shù)組等等) def flatten(nested): try: for sublist in nested: forelement in flatten(sublist): yield element except TypeError: yield nested list(flatten([1,[2,3],[4,[5,6]],7,8]))
當(dāng)函數(shù)被告知展開一個元素(元素?zé)o法展開,一個可迭代對象才能展開「鹫恕),for循環(huán)會引發(fā)一個TypeError異常籍琳。但上面的那種情況在處理元素是字符串的時候不適用菲宴。
def flatten(nested): try: # 不要迭代類似字符串的數(shù)據(jù)對象 try: nested + '' # 當(dāng)nested不是一個字符串的時候會引發(fā)一個TypeError except TypeError: pass else: raise TypeError for sublist in nested: for element in flatten(sublist): yield element except TypeError: yield nested # 下面的是可以打印出多層嵌套的數(shù)據(jù)(無論是一般數(shù)據(jù)還是字符串) def flatten(nested): try: if isinstance(nested, str): raise TypeError for sublist in nested: for element in sublist: yield element except TypeError: yield nested
?
-
生成器方法
-
send
可以改變生成器內(nèi)部值的方法
要在生成器掛起后才有意義(也就是說在yield函數(shù)第一次被運行之后),如果相對剛剛啟動的生成器使用send()方法趋急,可以講None作為其參數(shù)進行調(diào)用。
def repeater(value): while True: new = (yield value) if new is not None: value = new # 使用方法 r = repeater(42) r.next() r.send('Hello world!')
-
throw
用于在生成器內(nèi)引發(fā)一個異常(在yield表達式中)
def gen(): while True: try: yield 'normal value' yield 'normal value 2' print 'here' except ValueError: print 'we got ValueError here' except TypeError: break # gen()用法 g - gen() print next(g) print g.throw(Valueerror) print next(g) print g.throw(TypeError) """ 程序的輸出: print(next(g)):會輸出normal value谣蠢,并停留在yield ‘normal value 2’之前。 由于執(zhí)行了g.throw(ValueError)眉踱,所以會跳過所有后續(xù)的try語句霜威,也就是說yield ‘normal value 2’不會被執(zhí)行,然后進入到except語句侥祭,打印出we got ValueError here茄厘。然后再次進入到while語句部分谈宛,消耗一個yield,所以會輸出normal value吆录。 print(next(g)),會執(zhí)行yield ‘normal value 2’語句哀卫,并停留在執(zhí)行完該語句后的位置。 g.throw(TypeError):會跳出try語句此改,從而print(‘here’)不會被執(zhí)行侄柔,然后執(zhí)行break語句,跳出while循環(huán)暂题,然后到達程序結(jié)尾,所以跑出StopIteration異常纵苛。 """
-
close
它在yield運行處引發(fā)一個GeneratorExit異常,可以對生成器內(nèi)進行代碼清理言津,一般講yield語句放在try/finally語句中。執(zhí)行close()方法后贝椿,生成器對象就會被銷毀陷谱,不能再調(diào)用next()方法
def gen(): yield 1 yield 2 yield 3 g = gen() print next(g) g.close() next(g)
?
-
-