1. 程式人生 > 實用技巧 >Python itertools模組詳解

Python itertools模組詳解

Python itertools模組詳解

這貨很強大, 必須掌握

文件 連結http://docs.python.org/2/library/itertools.html

pymotw 連結http://pymotw.com/2/itertools/

基本是基於文件的翻譯和補充,相當於翻譯了

itertools用於高效迴圈的迭代函式集合

組成

總體,整體瞭解

無限迭代器

複製程式碼程式碼如下:
1 2 3 4 迭代器 引數 結果 例子 count() start, [step] start, start+step, start+2*step, ... count(10)-->1011
121314... cycle() p p0, p1, ... plast, p0, p1, ... cycle('ABCD')--> A B C D A B C D ... repeat() elem [,n] elem, elem, elem, ... endlesslyorup to n times repeat(10,3)-->101010

  


處理輸入序列迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 迭代器 引數 結果 例子 chain() p, q, ... p0, p1, ... plast, q0, q1, ... chain(
'ABC','DEF')--> A B C D E F compress() data, selectors (d[0]ifs[0]), (d[1]ifs[1]), ... compress('ABCDEF', [1,0,1,0,1,1])--> A C E F dropwhile() pred, seq seq[n], seq[n+1], starting when pred fails dropwhile(lambdax: x<5, [1,4,6,4,1])-->641 groupby() iterable[, keyfunc] sub-iterators grouped by value of keyfunc(v)
ifilter() pred, seq elements of seq where pred(elem)isTrueifilter(lambdax: x%2,range(10))-->13579 ifilterfalse() pred, seq elements of seq where pred(elem)isFalseifilterfalse(lambdax: x%2,range(10))-->02468 islice() seq, [start,] stop [, step] elementsfromseq[start:stop:step] islice('ABCDEFG',2,None)--> C D E F G imap() func, p, q, ... func(p0, q0), func(p1, q1), ... imap(pow, (2,3,10), (5,2,3))-->3291000 starmap() func, seq func(*seq[0]), func(*seq[1]), ... starmap(pow, [(2,5), (3,2), (10,3)])-->3291000 tee() it, n it1, it2 , ... itn splits one iterator into n takewhile() pred, seq seq[0], seq[1], until pred fails takewhile(lambdax: x<5, [1,4,6,4,1])-->14 izip() p, q, ... (p[0], q[0]), (p[1], q[1]), ... izip('ABCD','xy')--> Ax By izip_longest() p, q, ... (p[0], q[0]), (p[1], q[1]), ... izip_longest('ABCD','xy', fillvalue='-')--> Ax By C-D-

  

組合生成器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 迭代器 引數 結果 product() p, q, ... [repeat=1] cartesian product, equivalent to a nestedfor-loop permutations() p[, r] r-length tuples,allpossible orderings, no repeated elements combinations() p, r r-length tuples,insortedorder, no repeated elements combinations_with_replacement() p, r r-length tuples,insortedorder, with repeated elements product('ABCD', repeat=2) AA AB AC AD BA BB BC BD CA CB CC CD DA DB DC DD permutations('ABCD',2) AB AC AD BA BC BD CA CB CD DA DB DC combinations('ABCD',2) AB AC AD BC BD CD combinations_with_replacement('ABCD',2) AA AB AC AD BB BC BD CC CD DD

  

第一部分

itertools.count(start=0, step=1)

建立一個迭代器,生成從n開始的連續整數,如果忽略n,則從0開始計算(注意:此迭代器不支援長整數)

如果超出了sys.maxint,計數器將溢位並繼續從-sys.maxint-1開始計算。

定義

複製程式碼程式碼如下:
1 2 3 4 5 6 7 defcount(start=0, step=1): # count(10) --> 10 11 12 13 14 ... # count(2.5, 0.5) -> 2.5 3.0 3.5 ... n=start whileTrue: yieldn n+=step

  

等同於(start + step * i for i in count())

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 fromitertoolsimport* foriinizip(count(1), ['a','b','c']): printi (1,'a') (2,'b') (3,'c')

  

itertools.repeat(object[, times])

建立一個迭代器,重複生成object,times(如果已提供)指定重複計數,如果未提供times,將無止盡返回該物件。

定義

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 defrepeat(object, times=None): # repeat(10, 3) --> 10 10 10 iftimesisNone: whileTrue: yieldobject else: foriinxrange(times): yieldobject

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 fromitertoolsimport* foriinrepeat('over-and-over',5): printi over-and-over over-and-over over-and-over over-and-over over-and-over

  

第二部分
itertools.chain(*iterables)

將多個迭代器作為引數, 但只返回單個迭代器, 它產生所有引數迭代器的內容, 就好像他們是來自於一個單一的序列.

複製程式碼程式碼如下:
1 2 3 4 5 defchain(*iterables): # chain('ABC', 'DEF') --> A B C D E F foritiniterables: forelementinit: yieldelement

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 fromitertoolsimport* foriinchain([1,2,3], ['a','b','c']): printi 1 2 3 a b c fromitertoolsimportchain, imap defflatmap(f, items): returnchain.from_iterable(imap(f, items)) >>>list(flatmap(os.listdir, dirs)) >>> ['settings.py','wsgi.py','templates','app.py', 'templates','index.html, 'config.json']

  

itertools.compress(data, selectors)

提供一個選擇列表,對原始資料進行篩選

複製程式碼程式碼如下:
1 2 3 4 defcompress(data, selectors): # compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F return(dford, sinizip(data, selectors)ifs) itertools.dropwhile(predicate, iterable)

  


建立一個迭代器,只要函式predicate(item)為True,就丟棄iterable中的項,如果predicate返回False,就會生成iterable中的項和所有後續項。

即:在條件為false之後的第一次, 返回迭代器中剩下來的項.

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 defdropwhile(predicate, iterable): # dropwhile(lambda x: x<5, [1,4,6,4,1]) --> 6 4 1 iterable=iter(iterable) forxiniterable: ifnotpredicate(x): yieldx break forxiniterable: yieldx

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 fromitertoolsimport* defshould_drop(x): print'Testing:', x return(x<1) foriindropwhile(should_drop, [-1,0,1,2,3,4,1,-2]): print'Yielding:', i Testing:-1 Testing:0 Testing:1 Yielding:1 Yielding:2 Yielding:3 Yielding:4 Yielding:1 Yielding:-2

  

itertools.groupby(iterable[, key])

返回一個產生按照key進行分組後的值集合的迭代器.

如果iterable在多次連續迭代中生成了同一項,則會定義一個組,如果將此函式應用一個分類列表,那麼分組將定義該列表中的所有唯一項,key(如果已提供)是一個函式,應用於每一項,如果此函式存在返回值,該值將用於後續項而不是該項本身進行比較,此函式返回的迭代器生成元素(key, group),其中key是分組的鍵值,group是迭代器,生成組成該組的所有項。

即:按照keyfunc函式對序列每個元素執行後的結果分組(每個分組是一個迭代器), 返回這些分組的迭代器

等價於

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 classgroupby(object): # [k for k, g in groupby('AAAABBBCCDAABBB')] --> A B C D A B # [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D def__init__(self, iterable, key=None): ifkeyisNone: key=lambdax: x self.keyfunc=key self.it=iter(iterable) self.tgtkey=self.currkey=self.currvalue=object() def__iter__(self): returnself defnext(self): whileself.currkey==self.tgtkey: self.currvalue=next(self.it)# Exit on StopIteration self.currkey=self.keyfunc(self.currvalue) self.tgtkey=self.currkey return(self.currkey,self._grouper(self.tgtkey)) def_grouper(self, tgtkey): whileself.currkey==tgtkey: yieldself.currvalue self.currvalue=next(self.it)# Exit on StopIteration self.currkey=self.keyfunc(self.currvalue)

  

應用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 fromitertoolsimportgroupby qs=[{'date':1},{'date':2}] [(name,list(group))forname, groupinitertools.groupby(qs,lambdap:p['date'])] Out[77]: [(1, [{'date':1}]), (2, [{'date':2}])] >>>fromitertoolsimport* >>> a=['aa','ab','abc','bcd','abcde'] >>>fori, kingroupby(a,len): ...printi,list(k) ... 2['aa','ab'] 3['abc','bcd'] 5['abcde']

  

另一個例子

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 fromitertoolsimport* fromoperatorimportitemgetter d=dict(a=1, b=2, c=1, d=2, e=1, f=2, g=3) di=sorted(d.iteritems(), key=itemgetter(1)) fork, gingroupby(di, key=itemgetter(1)): printk,map(itemgetter(0), g) 1['a','c','e'] 2['b','d','f'] 3['g']

  

itertools.ifilter(predicate, iterable)

返回的是迭代器類似於針對列表的內建函式 filter() , 它只包括當測試函式返回true時的項. 它不同於 dropwhile()

建立一個迭代器,僅生成iterable中predicate(item)為True的項,如果predicate為None,將返回iterable中所有計算為True的項

對函式func執行返回真的元素的迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 defifilter(predicate, iterable): # ifilter(lambda x: x%2, range(10)) --> 1 3 5 7 9 ifpredicateisNone: predicate=bool forxiniterable: ifpredicate(x): yieldx

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 fromitertoolsimport* defcheck_item(x): print'Testing:', x return(x<1) foriinifilter(check_item, [-1,0,1,2,3,4,1,-2]): print'Yielding:', i Testing:-1 Yielding:-1 Testing:0 Yielding:0 Testing:1 Testing:2 Testing:3 Testing:4 Testing:1 Testing:-2 Yielding:-2

  

itertools.ifilterfalse(predicate, iterable)

和ifilter(函式相反 , 返回一個包含那些測試函式返回false的項的迭代器)

建立一個迭代器,僅生成iterable中predicate(item)為False的項,如果predicate為None,則返回iterable中所有計算為False的項 對函式func執行返回假的元素的迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 defifilterfalse(predicate, iterable): # ifilterfalse(lambda x: x%2, range(10)) --> 0 2 4 6 8 ifpredicateisNone: predicate=bool forxiniterable: ifnotpredicate(x): yieldx

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 fromitertoolsimport* defcheck_item(x): print'Testing:', x return(x<1) foriinifilterfalse(check_item, [-1,0,1,2,3,4,1,-2]): print'Yielding:', i Testing:-1 Testing:0 Testing:1 Yielding:1 Testing:2 Yielding:2 Testing:3 Yielding:3 Testing:4 Yielding:4 Testing:1 Yielding:1 Testing:-2

  

itertools.islice(iterable, stop)

itertools.islice(iterable, start, stop[, step])

返回的迭代器是返回了輸入迭代器根據索引來選取的項

建立一個迭代器,生成項的方式類似於切片返回值: iterable[start : stop : step],將跳過前start個項,迭代在stop所指定的位置停止,step指定用於跳過項的步幅。 與切片不同,負值不會用於任何start,stop和step, 如果省略了start,迭代將從0開始,如果省略了step,步幅將採用1.

返回序列seq的從start開始到stop結束的步長為step的元素的迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 defislice(iterable,*args): # islice('ABCDEFG', 2) --> A B # islice('ABCDEFG', 2, 4) --> C D # islice('ABCDEFG', 2, None) --> C D E F G # islice('ABCDEFG', 0, None, 2) --> A C E G s=slice(*args) it=iter(xrange(s.startor0, s.stoporsys.maxint, s.stepor1)) nexti=next(it) fori, elementinenumerate(iterable): ifi==nexti: yieldelement nexti=next(it)

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 fromitertoolsimport* print'Stop at 5:' foriinislice(count(),5): printi print'Start at 5, Stop at 10:' foriinislice(count(),5,10): printi print'By tens to 100:' foriinislice(count(),0,100,10): printi Stop at5: 0 1 2 3 4 Start at5, Stop at10: 5 6 7 8 9 By tens to100: 0 10 20 30 40 50 60 70 80 90

  

itertools.imap(function, *iterables)

建立一個迭代器,生成項function(i1, i2, ..., iN),其中i1,i2...iN分別來自迭代器iter1,iter2 ... iterN,如果function為None,則返回(i1, i2, ..., iN)形式的元組,只要提供的一個迭代器不再生成值,迭代就會停止。

即:返回一個迭代器, 它是呼叫了一個其值在輸入迭代器上的函式, 返回結果. 它類似於內建函式 map() , 只是前者在任意輸入迭代器結束後就停止(而不是插入None值來補全所有的輸入).

返回序列每個元素被func執行後返回值的序列的迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 defimap(function,*iterables): # imap(pow, (2,3,10), (5,2,3)) --> 32 9 1000 iterables=map(iter, iterables) whileTrue: args=[next(it)foritiniterables] iffunctionisNone: yieldtuple(args) else: yieldfunction(*args)

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fromitertoolsimport* print'Doubles:' foriinimap(lambdax:2*x,xrange(5)): printi print'Multiples:' foriinimap(lambdax,y:(x, y, x*y),xrange(5),xrange(5,10)): print'%d * %d = %d'%i Doubles: 0 2 4 6 8 Multiples: 0*5=0 1*6=6 2*7=14 3*8=24 4*9=36

  

itertools.starmap(function, iterable)

建立一個迭代器,生成值func(*item),其中item來自iterable,只有當iterable生成的項適用於這種呼叫函式的方式時,此函式才有效。

對序列seq的每個元素作為func的引數列表執行, 返回執行結果的迭代器

複製程式碼程式碼如下:
1 2 3 4 defstarmap(function, iterable): # starmap(pow, [(2,5), (3,2), (10,3)]) --> 32 9 1000 forargsiniterable: yieldfunction(*args)

  


使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 fromitertoolsimport* values=[(0,5), (1,6), (2,7), (3,8), (4,9)] foriinstarmap(lambdax,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

  

itertools.tee(iterable[, n=2])

返回一些基於單個原始輸入的獨立迭代器(預設為2). 它和Unix上的tee工具有點語義相似, 也就是說它們都重複讀取輸入裝置中的值並將值寫入到一個命名檔案和標準輸出中

從iterable建立n個獨立的迭代器,建立的迭代器以n元組的形式返回,n的預設值為2,此函式適用於任何可迭代的物件,但是,為了克隆原始迭代器,生成的項會被快取,並在所有新建立的迭代器中使用,一定要注意,不要在呼叫tee()之後使用原始迭代器iterable,否則快取機制可能無法正確工作。

把一個迭代器分為n個迭代器, 返回一個元組.預設是兩個

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 deftee(iterable, n=2): it=iter(iterable) deques=[collections.deque()foriinrange(n)] defgen(mydeque): whileTrue: ifnotmydeque:# when the local deque is empty newval=next(it)# fetch a new value and fordindeques:# load it to all the deques d.append(newval) yieldmydeque.popleft() returntuple(gen(d)fordindeques)

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 fromitertoolsimport* r=islice(count(),5) i1, i2=tee(r) foriini1: print'i1:', i foriini2: print'i2:', i i1:0 i1:1 i1:2 i1:3 i1:4 i2:0 i2:1 i2:2 i2:3 i2:4

  

itertools.takewhile(predicate, iterable)

和dropwhile相反

建立一個迭代器,生成iterable中predicate(item)為True的項,只要predicate計算為False,迭代就會立即停止。

即:從序列的頭開始, 直到執行函式func失敗.

複製程式碼程式碼如下:
1 2 3 4 5 6 7 deftakewhile(predicate, iterable): # takewhile(lambda x: x<5, [1,4,6,4,1]) --> 1 4 forxiniterable: ifpredicate(x): yieldx else: break

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 fromitertoolsimport* defshould_take(x): print'Testing:', x return(x<2) foriintakewhile(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

  

itertools.izip(*iterables)

返回一個合併了多個迭代器為一個元組的迭代器. 它類似於內建函式zip(), 只是它返回的是一個迭代器而不是一個列表

建立一個迭代器,生成元組(i1, i2, ... iN),其中i1,i2 ... iN 分別來自迭代器iter1,iter2 ... iterN,只要提供的某個迭代器不再生成值,迭代就會停止,此函式生成的值與內建的zip()函式相同。

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 izip(iter1, iter2, ... iterN): 返回:(it1[0],it2 [0], it3[0], ..), (it1[1], it2[1], it3[1], ..)... defizip(*iterables): # izip('ABCD', 'xy') --> Ax By iterators=map(iter, iterables) whileiterators: yieldtuple(map(next, iterators))

  

使用

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 fromitertoolsimport* foriinizip([1,2,3], ['a','b','c']): printi (1,'a') (2,'b') (3,'c')

  


itertools.izip_longest(*iterables[, fillvalue])

與izip()相同,但是迭代過程會持續到所有輸入迭代變數iter1,iter2等都耗盡為止,如果沒有使用fillvalue關鍵字引數指定不同的值,則使用None來填充已經使用的迭代變數的值。

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 classZipExhausted(Exception): pass defizip_longest(*args,**kwds): # izip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- fillvalue=kwds.get('fillvalue') counter=[len(args)-1] defsentinel(): ifnotcounter[0]: raiseZipExhausted counter[0]-=1 yieldfillvalue fillers=repeat(fillvalue) iterators=[chain(it, sentinel(), fillers)foritinargs] try: whileiterators: yieldtuple(map(next, iterators)) exceptZipExhausted: pass

  

第三部分

itertools.product(*iterables[, repeat])

笛卡爾積

建立一個迭代器,生成表示item1,item2等中的專案的笛卡爾積的元組,repeat是一個關鍵字引數,指定重複生成序列的次數。

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 defproduct(*args,**kwds): # product('ABCD', 'xy') --> Ax Ay Bx By Cx Cy Dx Dy # product(range(2), repeat=3) --> 000 001 010 011 100 101 110 111 pools=map(tuple, args)*kwds.get('repeat',1) result=[[]] forpoolinpools: result=[x+[y]forxinresultforyinpool] forprodinresult: yieldtuple(prod)

  

例子

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 importitertools a=(1,2,3) b=('A','B','C') c=itertools.product(a,b) foreleminc: printelem (1,'A') (1,'B') (1,'C') (2,'A') (2,'B') (2,'C') (3,'A') (3,'B') (3,'C')

  

itertools.permutations(iterable[, r])

排列

建立一個迭代器,返回iterable中所有長度為r的專案序列,如果省略了r,那麼序列的長度與iterable中的專案數量相同: 返回p中任意取r個元素做排列的元組的迭代器

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 defpermutations(iterable, r=None): # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC # permutations(range(3)) --> 012 021 102 120 201 210 pool=tuple(iterable) n=len(pool) r=nifrisNoneelser ifr > n: return indices=range(n) cycles=range(n, n-r,-1) yieldtuple(pool[i]foriinindices[:r]) whilen: foriinreversed(range(r)): cycles[i]-=1 ifcycles[i]==0: indices[i:]=indices[i+1:]+indices[i:i+1] cycles[i]=n-i else: j=cycles[i] indices[i], indices[-j]=indices[-j], indices[i] yieldtuple(pool[i]foriinindices[:r]) break else: return 也可以用product實現 defpermutations(iterable, r=None): pool=tuple(iterable) n=len(pool) r=nifrisNoneelser forindicesinproduct(range(n), repeat=r): iflen(set(indices))==r: yieldtuple(pool[i]foriinindices)

  

itertools.combinations(iterable, r)

建立一個迭代器,返回iterable中所有長度為r的子序列,返回的子序列中的項按輸入iterable中的順序排序 (不帶重複)

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 defcombinations(iterable, r): # combinations('ABCD', 2) --> AB AC AD BC BD CD # combinations(range(4), 3) --> 012 013 023 123 pool=tuple(iterable) n=len(pool) ifr > n: return indices=range(r) yieldtuple(pool[i]foriinindices) whileTrue: foriinreversed(range(r)): ifindices[i] !=i+n-r: break else: return indices[i]+=1 forjinrange(i+1, r): indices[j]=indices[j-1]+1 yieldtuple(pool[i]foriinindices)

  


#或者

1 2 3 4 5 6 defcombinations(iterable, r): pool=tuple(iterable) n=len(pool) forindicesinpermutations(range(n), r): ifsorted(indices)==list(indices): yieldtuple(pool[i]foriinindices)

  

itertools.combinations_with_replacement(iterable, r)

建立一個迭代器,返回iterable中所有長度為r的子序列,返回的子序列中的項按輸入iterable中的順序排序 (帶重複)

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 defcombinations_with_replacement(iterable, r): # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC pool=tuple(iterable) n=len(pool) ifnotnandr: return indices=[0]*r yieldtuple(pool[i]foriinindices) whileTrue: foriinreversed(range(r)): ifindices[i] !=n-1: break else: return indices[i:]=[indices[i]+1]*(r-i) yieldtuple(pool[i]foriinindices)

  


或者
1 2 3 4 5 6 defcombinations_with_replacement(iterable, r): pool=tuple(iterable) n=len(pool) forindicesinproduct(range(n), repeat=r): ifsorted(indices)==list(indices): yieldtuple(pool[i]foriinindices)

  

第四部分

擴充套件

使用現有擴充套件功能

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 deftake(n, iterable): "Return first n items of the iterable as a list" returnlist(islice(iterable, n)) deftabulate(function, start=0): "Return function(0), function(1), ..." returnimap(function, count(start)) defconsume(iterator, n): "Advance the iterator n-steps ahead. If n is none, consume entirely." # Use functions that consume iterators at C speed. ifnisNone: # feed the entire iterator into a zero-length deque collections.deque(iterator, maxlen=0) else: # advance to the empty slice starting at position n next(islice(iterator, n, n),None) defnth(iterable, n, default=None): "Returns the nth item or a default value" returnnext(islice(iterable, n,None), default) defquantify(iterable, pred=bool): "Count how many times the predicate is true" returnsum(imap(pred, iterable)) defpadnone(iterable): """Returns the sequence elements and then returns None indefinitely. Useful for emulating the behavior of the built-in map() function. """ returnchain(iterable, repeat(None)) defncycles(iterable, n): "Returns the sequence elements n times" returnchain.from_iterable(repeat(tuple(iterable), n)) defdotproduct(vec1, vec2): returnsum(imap(operator.mul, vec1, vec2)) defflatten(listOfLists): "Flatten one level of nesting" returnchain.from_iterable(listOfLists) defrepeatfunc(func, times=None,*args): """Repeat calls to func with specified arguments. Example: repeatfunc(random.random) """ iftimesisNone: returnstarmap(func, repeat(args)) returnstarmap(func, repeat(args, times)) defpairwise(iterable): "s -> (s0,s1), (s1,s2), (s2, s3), ..." a, b=tee(iterable) next(b,None) returnizip(a, b) defgrouper(iterable, n, fillvalue=None): "Collect data into fixed-length chunks or blocks" # grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx args=[iter(iterable)]*n returnizip_longest(fillvalue=fillvalue,*args) defroundrobin(*iterables): "roundrobin('ABC', 'D', 'EF') --> A D E B F C" # Recipe credited to George Sakkis pending=len(iterables) nexts=cycle(iter(it).nextforitiniterables) whilepending: try: fornextinnexts: yieldnext() exceptStopIteration: pending-=1 nexts=cycle(islice(nexts, pending)) defpowerset(iterable): "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)" s=list(iterable) returnchain.from_iterable(combinations(s, r)forrinrange(len(s)+1)) defunique_everseen(iterable, key=None): "List unique elements, preserving order. Remember all elements ever seen." # unique_everseen('AAAABBBCCDAABBB') --> A B C D # unique_everseen('ABBCcAD', str.lower) --> A B C D seen=set() seen_add=seen.add ifkeyisNone: forelementinifilterfalse(seen.__contains__, iterable): seen_add(element) yieldelement else: forelementiniterable: k=key(element) ifknotinseen: seen_add(k) yieldelement defunique_justseen(iterable, key=None): "List unique elements, preserving order. Remember only the element just seen." # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B # unique_justseen('ABBCcAD', str.lower) --> A B C A D returnimap(next, imap(itemgetter(1), groupby(iterable, key))) defiter_except(func, exception, first=None): """ Call a function repeatedly until an exception is raised. Converts a call-until-exception interface to an iterator interface. Like __builtin__.iter(func, sentinel) but uses an exception instead of a sentinel to end the loop. Examples: bsddbiter = iter_except(db.next, bsddb.error, db.first) heapiter = iter_except(functools.partial(heappop, h), IndexError) dictiter = iter_except(d.popitem, KeyError) dequeiter = iter_except(d.popleft, IndexError) queueiter = iter_except(q.get_nowait, Queue.Empty) setiter = iter_except(s.pop, KeyError) """ try: iffirstisnotNone: yieldfirst() while1: yieldfunc() exceptexception: pass defrandom_product(*args,**kwds): "Random selection from itertools.product(*args, **kwds)" pools=map(tuple, args)*kwds.get('repeat',1) returntuple(random.choice(pool)forpoolinpools) defrandom_permutation(iterable, r=None): "Random selection from itertools.permutations(iterable, r)" pool=tuple(iterable) r=len(pool)ifrisNoneelser returntuple(random.sample(pool, r)) defrandom_combination(iterable, r): "Random selection from itertools.combinations(iterable, r)" pool=tuple(iterable) n=len(pool) indices=sorted(random.sample(xrange(n), r)) returntuple(pool[i]foriinindices) defrandom_combination_with_replacement(iterable, r): "Random selection from itertools.combinations_with_replacement(iterable, r)" pool=tuple(iterable) n=len(pool) indices=sorted(random.randrange(n)foriinxrange(r)) returntuple(pool[i]foriinindices) deftee_lookahead(t, i): """Inspect the i-th upcomping value from a tee object while leaving the tee object at its current position. Raise an IndexError if the underlying iterator doesn't have enough values. """ forvalueinislice(t.__copy__(), i,None): returnvalue raiseIndexError(i)

  

自定義擴充套件

將序列按大小切分,更好的效能

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 fromitertoolsimportchain, islice defchunks(iterable, size,format=iter): it=iter(iterable) whileTrue: yieldformat(chain((it.next(),), islice(it, size-1))) >>> l=["a","b","c","d","e","f","g"] >>>forchunkinchunks(l,3,tuple):... printchunk... ("a","b","c") ("d","e","f") ("g",)

  

補充

迭代工具,你最好的朋友

迭代工具模組包含了操做指定的函式用於操作迭代器。想複製一個迭代器出來?連結兩個迭代器?以one liner(這裡的one-liner只需一行程式碼能搞定的任務)用內嵌的列表組合一組值?不使用list建立Map/Zip?···,你要做的就是 import itertools,舉個例子吧:

四匹馬賽跑到達終點排名的所有可能性:

複製程式碼程式碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 >>> horses=[1,2,3,4] >>> races=itertools.permutations(horses) >>>print(races) <itertools.permutationsobjectat0xb754f1dc]]> >>>print(list(itertools.permutations(horses))) [(1,2,3,4), (1,2,4,3), (1,3,2,4), (1,3,4,2), (1,4,2,3), (1,4,3,2), (2,1,3,4), (2,1,4,3), (2,3,1,4), (2,3,4,1), (2,4,1,3), (2,4,3,1), (3,1,2,4), (3,1,4,2), (3,2,1,4), (3,2,4,1), (3,4,1,2), (3,4,2,1), (4,1,2,3), (4,1,3,2), (4,2,1,3), (4,2,3,1), (4,3,1,2), (4,3,2,1)]

  

理解迭代的內部機制: 迭代(iteration)就是對可迭代物件(iterables,實現了__iter__()方法)和迭代器(iterators,實現了__next__()方法)的一個操作過程。可迭代物件是任何可返回一個迭代器的物件,迭代器是應用在迭代物件中迭代的物件,換一種方式說的話就是:iterable物件的__iter__()方法可以返回iterator物件,iterator通過呼叫next()方法獲取其中的每一個值(譯者注),讀者可以結合Java API中的 Iterable介面和Iterator介面進行類比。