Python: itertools模塊任性迭代

Python基礎(chǔ)文章集合請移步论悴。

itertools 模塊

該模塊包含了一系列處理可迭代對象(sequence-like)的函數(shù)移层,從此迭代更任性漠酿。

迭代器有一些特點(diǎn),比如lazy吉嚣,也就是只有用到的時候才讀入到內(nèi)存里梢薪,這樣更快更省內(nèi)存;比如只能調(diào)用一次尝哆,會被消耗掉秉撇。

import itertools as itls

合并迭代器: chain()與izip()

chain()函數(shù)接收n個可迭代對象,然后返回一個他們的合集的迭代器秋泄,縱向合并琐馆,上例子。

for i in itls.chain([1,2,3],['a','b','c']):
    print i,
1 2 3 a b c

izip()函數(shù)接收n個可迭代對象恒序,然后將其合并成tuples瘦麸,橫向合并,功能類似zip()歧胁,只是返回的是iterator滋饲,而不是list。

for i, j in itls.izip([1,2,3],['a','b','c']):
    print i, j
1 a
2 b
3 c

切分迭代器: islice()

islice()函數(shù)接收一個迭代器喊巍,然后返回其切片屠缭,類似于listslice切片操作。參數(shù)有start崭参,stopstep呵曹,其中startstep參數(shù)時可選參數(shù)。

print "Stop at 5:"
for i in itls.islice(itls.count(),5):
    print i,
Stop at 5:
0 1 2 3 4
print "Start at 5, Stop at 10:"
for i in itls.islice(itls.count(),5,10):
    print i,
Start at 5, Stop at 10:
5 6 7 8 9
print "By tens to 100:"
for i in itls.islice(itls.count(),0,100,10):
    print i,
By tens to 100:
0 10 20 30 40 50 60 70 80 90

復(fù)制迭代器: tee()

與Unix里tee方法語意一樣何暮,這里接收一個迭代器奄喂,然后返回n個(default 2)一樣的迭代器。

r = itls.islice(itls.count(),4)
i1, i2, i3 = itls.tee(r,3) # i1 and i2, like a copy

for i, j, k in itls.izip(i1,i2,i3):
    print i, j, k
0 0 0
1 1 1
2 2 2
3 3 3

有一點(diǎn)值得注意海洼,初始的iterator不宜繼續(xù)使用砍聊,如果你使用(consume),那新的迭代器就不會產(chǎn)生這些值了贰军,見例子玻蝌。

r = itls.islice(itls.count(),4)
i1, i2 = itls.tee(r)
for i in r:
    print 'r:', i
    if i > 0:
        break
for i in i1:
    print 'i1:', i

for i in i2:
    print 'i2:', i
r: 0
r: 1
i1: 2
i1: 3
i2: 2
i2: 3

可以看出,初始迭代器消耗了0,1词疼,在新產(chǎn)生的迭代器里俯树,就不會出現(xiàn)這些值了。

Map迭代器

imap()函數(shù)對迭代器進(jìn)行轉(zhuǎn)換贰盗,類似于python內(nèi)置的map()函數(shù)许饿。下例把xrange(5)乘以2。

print "Doubles:"
for i in itls.imap(lambda x: 2*x, xrange(5)):
    print i,
Doubles:
0 2 4 6 8

imap()可以同時接受多個可迭代對象舵盈,進(jìn)行map操作陋率。

print "Multiples:"
for i in itls.imap(lambda x,y:(x, y, x*y), xrange(5),xrange(5,10)):
    print '%d * %d = %d' % i
Multiples:
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36

starmap()imap()功能類似球化,但有點(diǎn)區(qū)別,starmap()可以從tuple里解析出多個參數(shù)瓦糟,而imap()只能從多個課迭代對象獲取多個參數(shù)筒愚,看例子。

values = [(0, 5), (1, 6), (2, 7), (3, 8), (4, 9)]
for i in itls.starmap(lambda x,y:(x,y,x*y), values):
    print '%d * %d = %d' % i
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 8 = 24
4 * 9 = 36

產(chǎn)生新迭代器

count()菩浙,cycle()repeat()函數(shù)提供了幾個產(chǎn)生迭代器的便捷操作巢掺,非常nice。

count()

產(chǎn)生連續(xù)的整數(shù)劲蜻,有下限(默認(rèn)0)陆淀,沒有上限(可以用xrange())。

for i in itls.izip(itls.count(1),['a','b','c']):
    print i
(1, 'a')
(2, 'b')
(3, 'c')

cycle()

無限重復(fù)給定的可迭代對象先嬉。

i = 0
for item in itls.cycle(['a','b','c']):
    i += 1
    if i == 7:
        break
    print (i, item)
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'a')
(5, 'b')
(6, 'c')

repeat()

重復(fù)給定的值轧苫,n次。

for i in itls.repeat('over-and-over',3):
    print i
over-and-over
over-and-over
over-and-over

當(dāng)需要給一個序列添加一個不變對象的時候疫蔓,用repeat()imap()izip()的combo特別有用含懊。

for i,s in itls.izip(itls.count(), itls.repeat('over-and-over',3)):
    print i, s
0 over-and-over
1 over-and-over
2 over-and-over
for i in itls.imap(lambda x,y:(x,y,x*y),itls.repeat(2),xrange(5)):
    print '%d * %d = %d' % i
2 * 0 = 0
2 * 1 = 2
2 * 2 = 4
2 * 3 = 6
2 * 4 = 8

過濾迭代器

類似于內(nèi)置的filter()功能,實(shí)現(xiàn)迭代器的篩選鳄袍。

dropwhile()

對item進(jìn)行判斷绢要,如果判斷為True吏恭,繼續(xù)拗小;如果判斷為False,不繼續(xù)drop了樱哼,只drop之前判斷為True的哀九,保留之后的所有items,不再進(jìn)行判斷搅幅,全部保留阅束。

def should_drop(x):
    print 'Testing:', x
    return x < 1
for i in itls.dropwhile(should_drop,[ -1, 0, 1, 2, 3, 1, -2 ]):
    print 'Yielding:', i
Testing: -1
Testing: 0
Testing: 1
Yielding: 1
Yielding: 2
Yielding: 3
Yielding: 1
Yielding: -2

takewhile()

dropwhile()功能相反,當(dāng)判斷為False的時候茄唐,就不繼續(xù)take了息裸,只保留之前判斷為真item。

def should_take(x):
    print 'Testing:', x
    return x < 2
for i in itls.takewhile(should_take,[ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    print 'Yielding:', i
Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Yielding: 1
Testing: 2

ifilter()

dropwhile()takewhile()都不是對所有元素過濾沪编,而ifilter()則盡職盡責(zé)地對所有元素過濾呼盆。與其對應(yīng)的是ifilterfalse(),只保留判定為False的item蚁廓。

def check_item(x):
    print 'Testing:', x
    return x < 1
for i in itls.ifilter(check_item, [ -1, 0, 1, 2, 3, -2 ]):
    print 'Yielding:', i
Testing: -1
Yielding: -1
Testing: 0
Yielding: 0
Testing: 1
Testing: 2
Testing: 3
Testing: -2
Yielding: -2

Group迭代器

groupby(iterable[, keyfunc]) Create an iterator which returns(key, sub-iterator) grouped by each value of key(value)

按給定的key對可迭代對象分組访圃,返回sub-iterator

things = [("animal", "bear"), ("animal", "duck"), ("plant", "cactus"), ("vehicle", "speed boat"), ("vehicle", "school bus")]

groupby()接收兩個參數(shù)相嵌,一個the data to group腿时,一個是the function to group it with况脆。

for key, group in itls.groupby(things, lambda x: x[0]):
    print key, group
animal <itertools._grouper object at 0x10bce2150>
plant <itertools._grouper object at 0x10bce2190>
vehicle <itertools._grouper object at 0x10bce2150>

可以看出,分組后批糟,返回三個sub-iterator格了,我們可以再用一層循環(huán)訪問。

for key, group in itls.groupby(things, lambda x:x[0]):
    for thing in group:
        print "A %s is a %s." % (thing[1], key)
    print ""
A bear is a animal.
A duck is a animal.

A cactus is a plant.

A speed boat is a vehicle.
A school bus is a vehicle.

且慢跃赚,值得注意的一點(diǎn)是笆搓,在group之前,務(wù)必要按key排序纬傲,因?yàn)?code>groupby方法遍歷對象满败,當(dāng)key變化的時候,就會新產(chǎn)生一個group叹括。有例為證算墨!

things = [("animal", "bear"), ("plant", "cactus"), ("animal", "duck")]
for key, group in itls.groupby(things, lambda x: x[0]):
    print key, group
animal <itertools._grouper object at 0x10bce2410>
plant <itertools._grouper object at 0x10bce2490>
animal <itertools._grouper object at 0x10bce2410>

本來是應(yīng)該分兩組的,結(jié)果是三組汁雷,就是因?yàn)闆]有排序净嘀。

new_things = sorted(things,key=lambda x: x[0])
for key, group in itls.groupby(new_things, lambda x:x[0]):
    print key, group
animal <itertools._grouper object at 0x10bce2350>
plant <itertools._grouper object at 0x10bce2410>

這個看上去就對了!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侠讯,一起剝皮案震驚了整個濱河市挖藏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厢漩,老刑警劉巖膜眠,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異溜嗜,居然都是意外死亡宵膨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門炸宵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辟躏,“玉大人,你說我怎么就攤上這事土全∩铀觯” “怎么了?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵裹匙,是天一觀的道長瑞凑。 經(jīng)常有香客問我,道長幻件,這世上最難降的妖魔是什么拨黔? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上篱蝇,老公的妹妹穿的比我還像新娘贺待。我一直安慰自己,他們只是感情好零截,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布麸塞。 她就那樣靜靜地躺著,像睡著了一般涧衙。 火紅的嫁衣襯著肌膚如雪哪工。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天弧哎,我揣著相機(jī)與錄音雁比,去河邊找鬼。 笑死撤嫩,一個胖子當(dāng)著我的面吹牛偎捎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播序攘,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茴她,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了程奠?” 一聲冷哼從身側(cè)響起丈牢,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瞄沙,沒想到半個月后己沛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡帕识,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年泛粹,在試婚紗的時候發(fā)現(xiàn)自己被綠了遂铡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肮疗。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖扒接,靈堂內(nèi)的尸體忽然破棺而出伪货,到底是詐尸還是另有隱情,我是刑警寧澤钾怔,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布碱呼,位于F島的核電站,受9級特大地震影響宗侦,放射性物質(zhì)發(fā)生泄漏愚臀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一矾利、第九天 我趴在偏房一處隱蔽的房頂上張望姑裂。 院中可真熱鬧馋袜,春花似錦、人聲如沸舶斧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽茴厉。三九已至泽台,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間矾缓,已是汗流浹背怀酷。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗜闻,地道東北人胰坟。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像泞辐,于是被迫代替她去往敵國和親笔横。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容