使用示例1:創(chuàng)建處理數(shù)據(jù)的管道
具體描述:我們想以流水線式的形式對(duì)數(shù)據(jù)進(jìn)行迭代處理(類似Unix下的管道)檩电。比方說(shuō)我們有海量的數(shù)據(jù)需要處理赖钞,但是沒(méi)法完全的將數(shù)據(jù)加載到內(nèi)存中去眠饮。
解決方案:生成器函數(shù)是一種實(shí)現(xiàn)管道機(jī)制的好方法(具體代碼不做描述了殷勘,這里簡(jiǎn)單介紹下原理)
原理剖析:
1椰苟、yield語(yǔ)句表現(xiàn)為數(shù)據(jù)的生產(chǎn)者磁餐,for循環(huán)表現(xiàn)為數(shù)據(jù)的消費(fèi)者;
2幼衰、由于處理過(guò)程的迭代特性靴跛,這里只會(huì)用到非常少的內(nèi)存。
使用示例2:我們有一個(gè)嵌套序列渡嚣,想將它扁平化處理為一列單獨(dú)的值
解決方案:通過(guò)寫(xiě)一個(gè)帶有yield from語(yǔ)句的遞歸生成器函數(shù)來(lái)解決
import collections
def flatten(items, ingore_types=(str, bytes)):
for x in items:
# isinstance(x, collections.Iterable) 檢查是否有某個(gè)元素是可迭代的梢睛;
# 如果有,那么就用yield from將這個(gè)可迭代對(duì)象作為一種子例程進(jìn)行遞歸识椰,它將所有的值都產(chǎn)生出來(lái)
if isinstance(x, collections.Iterable) and not isinstance(x, ingore_types):
# not isinstance(x, ingore_types)是為了避免將字符串和字節(jié)串解釋為可迭代對(duì)象绝葡,進(jìn)而將他們展開(kāi)為單獨(dú)的一個(gè)個(gè)字符
yield from flatten(x)
else:
yield x
items = [1, 2, [3, 4, [5, 6], 7], 8]
for x in flatten(items):
print(x)
1
2
3
4
5
6
7
8
關(guān)于為何過(guò)濾not isinstance(x, ingore_types), 實(shí)例如下:
items = ['Dave', 'Paula', ['Thomas', 'Lewis']]
for x in flatten(items): # 輸出了整個(gè)字符串(并沒(méi)有迭代字符串)
print(x)
Dave
Paula
Thomas
Lewis
總結(jié):
如果想編寫(xiě)生成器用來(lái)把其他的生成器當(dāng)做子例程來(lái)調(diào)用,yield from是個(gè)不錯(cuò)的快捷方式腹鹉。