标准库中的生成器函数

这里主要记录流畅的Python书中P349页介绍关于内置itertoos模块中的内置生成器。(19个)

 

第一组是用于过滤的生成器函数:从输入的可迭代对象中产出元素的子集,而且不修改元素本身。

 

compress(it, selector_it)

In [133]: compress?                                                                                  
Init signature: compress(self, /, *args, **kwargs)
Docstring:     
compress(data, selectors) --> iterator over selected data

Return data elements corresponding to true selector elements.
Forms a shorter iterator from selected data elements using the
selectors to choose the data elements.
Type:           type
Subclasses:     

 并行处理两个可迭代对象;如果selector_it中的元素是真值,产出it中对应的元素。

In [134]: com = compress('123456789',[1,0,1,False,'',True])                                          

In [135]: com                                                                                        
Out[135]: <itertools.compress at 0x1105c8e10>

In [136]: list(com)                                                                                  
Out[136]: ['1', '3', '6']

In [137]:  

 

dropwhile与takewhile

dropwhile(predicate, it):

处理it,跳过predicate的计算为真的值,然后产出剩下的各个元素(剩下的元素不在检查)

takewhile(predicate, it):

处理it,predicate返回为真值的产出对应元素,遇到返回为假,立即停止,不在继续检查(剩下的元素不在检查)

两个蛮有意思的返回生成器的类,第一个,返回是真的都跳过,遇到一个假的,后面的都要.(取后面)

第二个,遇到真的都要,遇到假的后面都不要。(取前面)

In [137]: drop = dropwhile(lambda x:x<3,range(5))                                                    

In [138]: list(drop)                                                                                 
Out[138]: [3, 4]

In [139]: type(dropwhile)                                                                            
Out[139]: type

In [140]: drop = dropwhile(lambda x:x != 'a','cccaddd')                                              

In [141]: list(drop)                                                                                 
Out[141]: ['a', 'd', 'd', 'd']

In [142]:  

 

In [142]: take = takewhile(lambda x:x <5,count(1,3))                                                 

In [143]: list(take)                                                                                 
Out[143]: [1, 4]

In [144]:  

 

filter与filterfalse(遍历全部元素)

filter(predicate, it):逐个遍历it中的所有元素,放入predicate,返回predicate返回是真的值的元素。

filterflase(predicate, it):逐个遍历it中的所有元素,放入predicate,返回predicate返回是假的值的元素。

In [144]: vowel = lambda x: x.lower() in 'aeiou'                                                     

In [145]: list(filter(vowel,'Aardvark'))                                                             
Out[145]: ['A', 'a', 'a']

In [146]: list(filterfalse(vowel,'Aardvark'))                                                        
Out[146]: ['r', 'd', 'v', 'r', 'k']

In [147]:  

 

islice(it, stop)或islice(it, start,stop,step=1)

产出it的切片,作用类似于s[:stop]或s[start:stop:strp],不过it可以是任何可迭代对象,而且这个类实现是惰性操作。

实际操作跟这个功能一样iter(it[:stop])或iter(it[start:stop:step=1])

In [160]: list(islice('Aardvark',4))                                                                 
Out[160]: ['A', 'a', 'r', 'd']

In [161]: list(islice('Aardvark',4,7))                                                               
Out[161]: ['v', 'a', 'r']

In [162]: list(islice('Aardvark',4,7,2))                                                             
Out[162]: ['v', 'r']

In [163]: list(iter('Aardvark'[4:7:2]))                                                              
Out[163]: ['v', 'r']

In [164]:  

 

 

用于映射的生成器类。(扫描全部元素)

accmulate(it,[func])

产出累积的总和,如果提供了func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果。

n [167]: import random                                                                              

In [168]: sample = list(range(10))                                                                   

In [169]: random.shuffle(sample)                                                                     

In [170]: sample                                                                                     
Out[170]: [5, 2, 3, 1, 4, 0, 6, 9, 7, 8]

In [171]: list(accumulate(sample))                                                                   
Out[171]: [5, 7, 10, 11, 15, 15, 21, 30, 37, 45]


In [173]: list(accumulate(sample,max))                                                               
Out[173]: [5, 5, 5, 5, 5, 5, 6, 9, 9, 9]

In [174]: list(accumulate(sample,min))                                                               
Out[174]: [5, 2, 2, 1, 1, 0, 0, 0, 0, 0]

In [175]: from operator import mul                                                                   

In [176]: list(accumulate(sample,mul))                                                               
Out[176]: [5, 10, 30, 30, 120, 0, 0, 0, 0, 0]

In [177]:                                                                                            

 

emumetate(iterable, start=0)(内置)

产出两个元素组成的元祖,结构是(index,item),其中index从start开始计算,item则从iterable中获取

In [177]: list(enumerate('hello'))                                                                   
Out[177]: [(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]

In [178]: list(enumerate(range(1,10),start=1))                                                       
Out[178]: [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6), (7, 7), (8, 8), (9, 9)]

In [179]:  

 

 map(func,it1,[it2,...itN])(内置)

把it中的各个元素传给func,产出结果,如果传入N个可迭代对象,那么func必须能接收N个参数,而且也要并行处理各个可迭代对象。

In [179]: list(map(mul,range(11),range(11)))                                                         
Out[179]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

In [180]: list(map(mul,range(11),(1,2,3)))                                                           
Out[180]: [0, 2, 6]

In [181]: list(map(lambda a,b:(a,b),range(11),(1,2,3)))                                              
Out[181]: [(0, 1), (1, 2), (2, 3)]

In [182]:     

 

starmap(func, it)

把it中的各个元素传给func,产出结果;输入的可迭代对象产出可迭代的元素iit,然后以func(*iit)这种形式调用func

讲的很抽象,或者翻译的很差,其实简单来说,it里买的元素必须是可解包的元素,每次返回的是解包后的参数,传递给func返回的值。

In [182]: list(starmap(mul,enumerate('albatroz',1)))                                                 
Out[182]: ['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']

In [183]: sample                                                                                     
Out[183]: [5, 2, 3, 1, 4, 0, 6, 9, 7, 8]

In [184]: list(starmap(lambda a,b:b/a,enumerate(sample,1)))                                          
Out[184]: 
[5.0,
 1.0,
 1.0,
 0.25,
 0.8,
 0.0,
 0.8571428571428571,
 1.125,
 0.7777777777777778,
 0.8]

In [185]:       

 我搞个简单的看看,就比较直接。

In [186]: list(starmap(add,((1,2),(3,4))))                                                           
Out[186]: [3, 7]

In [187]:  

 

In [187]: a = 1,2,3                                                                                  

In [188]: b = 2,3,4                                                                                  

In [189]: lz = zip(a,b)                                                                              

In [190]: list(starmap(add,lz))                                                                      
Out[190]: [3, 5, 7]

In [191]:     

 

合并多个可迭代对象的生成器类

chain(it1,...,itN)

先产出it1中的所有元素,然后产出it2中的所有元素,以此类推,无缝连接在一起

In [200]: list(chain.from_iterable(('12345',[1],('c'))))                                             
Out[200]: ['1', '2', '3', '4', '5', 1, 'c']

In [201]: list(chain('abc,',range(10)))                                                              
Out[201]: ['a', 'b', 'c', ',', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [202]: list(chain(enumerate('hello')))                                                            
Out[202]: [(0, 'h'), (1, 'e'), (2, 'l'), (3, 'l'), (4, 'o')]

In [203]: list(chain.from_iterable(enumerate('hello')))                                              
Out[203]: [0, 'h', 1, 'e', 2, 'l', 3, 'l', 4, 'o']

In [204]:  

 chain.from_iterable(it)

从it这个可迭代对象中取出元素,每个元素为可迭代对象,然后把所有的it中的所有元素无缝连接在一起。

上面已经示例了。

 

zip(it1.....,itN)(内置)

并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元祖,只要有一个可迭代的对象到头了,就停止。

 

zip_longest(it1,....,itN, fillvalue=None)

并行从输入的各个可迭代对象中获取元素,产出由N个元素组成的元祖,等到最长的可迭代对象到头才停止,空缺的值使用fillvalue填充。

In [206]: list(zip('abc',range(10)))                                                                 
Out[206]: [('a', 0), ('b', 1), ('c', 2)]

In [207]: list(zip('abc',range(100),[3,4,5,6]))                                                      
Out[207]: [('a', 0, 3), ('b', 1, 4), ('c', 2, 5)]

In [208]: list(zip_longest('abc',range(8),[1,2],fillvalue='?'))                                      
Out[208]: 
[('a', 0, 1),
 ('b', 1, 2),
 ('c', 2, '?'),
 ('?', 3, '?'),
 ('?', 4, '?'),
 ('?', 5, '?'),
 ('?', 6, '?'),
 ('?', 7, '?')]

In [209]:    

 

product(it1,...itN, repeat=1)

计算迪凯尔积:从输入的各个可迭代对象中获取元素,合并成有N个元素组成的元祖,与嵌套的for循环效果一样;repeat指明重复处理多少次输入的可迭代对象。

普通两个可迭代对象,就像双层的for循环返回的元祖组合。

In [209]: list(product('ABC','ABc'))                                                                 
Out[209]: 
[('A', 'A'),
 ('A', 'B'),
 ('A', 'c'),
 ('B', 'A'),
 ('B', 'B'),
 ('B', 'c'),
 ('C', 'A'),
 ('C', 'B'),
 ('C', 'c')]

In [210]: list(product('abc',range(2)))                                                              
Out[210]: [('a', 0), ('a', 1), ('b', 0), ('b', 1), ('c', 0), ('c', 1)]

In [211]: suits = 'spades hearts diamonds clubs'.split()                                             

In [212]: list(product('AK',suits))                                                                  
Out[212]: 
[('A', 'spades'),
 ('A', 'hearts'),
 ('A', 'diamonds'),
 ('A', 'clubs'),
 ('K', 'spades'),
 ('K', 'hearts'),
 ('K', 'diamonds'),
 ('K', 'clubs')]

In [213]: list(product('ABC'))                                                                       
Out[213]: [('A',), ('B',), ('C',)]

In [214]: list(product('ABC',repeat=2))                                                              
Out[214]: 
[('A', 'A'),
 ('A', 'B'),
 ('A', 'C'),
 ('B', 'A'),
 ('B', 'B'),
 ('B', 'C'),
 ('C', 'A'),
 ('C', 'B'),
 ('C', 'C')]

In [215]: list(product('ABC','ABC'))                                                                 
Out[215]: 
[('A', 'A'),
 ('A', 'B'),
 ('A', 'C'),
 ('B', 'A'),
 ('B', 'B'),
 ('B', 'C'),
 ('C', 'A'),
 ('C', 'B'),
 ('C', 'C')]

In [216]: list(product('AB',range(2),repeat=2))                                                      
Out[216]: 
[('A', 0, 'A', 0),
 ('A', 0, 'A', 1),
 ('A', 0, 'B', 0),
 ('A', 0, 'B', 1),
 ('A', 1, 'A', 0),
 ('A', 1, 'A', 1),
 ('A', 1, 'B', 0),
 ('A', 1, 'B', 1),
 ('B', 0, 'A', 0),
 ('B', 0, 'A', 1),
 ('B', 0, 'B', 0),
 ('B', 0, 'B', 1),
 ('B', 1, 'A', 0),
 ('B', 1, 'A', 1),
 ('B', 1, 'B', 0),
 ('B', 1, 'B', 1)]

In [217]: list(product('AB',range(2),'AB',range(2)))                                                 
Out[217]: 
[('A', 0, 'A', 0),
 ('A', 0, 'A', 1),
 ('A', 0, 'B', 0),
 ('A', 0, 'B', 1),
 ('A', 1, 'A', 0),
 ('A', 1, 'A', 1),
 ('A', 1, 'B', 0),
 ('A', 1, 'B', 1),
 ('B', 0, 'A', 0),
 ('B', 0, 'A', 1),
 ('B', 0, 'B', 0),
 ('B', 0, 'B', 1),
 ('B', 1, 'A', 0),
 ('B', 1, 'A', 1),
 ('B', 1, 'B', 0),
 ('B', 1, 'B', 1)]

In [218]:      

 product返回的都是元祖的组合,product里面有几个可迭代元素,就代码这个生成的元素内元祖的元素数量,repert默认为1,设置不同的repert可以看出就是重复带入一遍前面的可迭代元素。

 

把输入的各个元素扩展成多个输出的生成器函数。(要么接收一个可迭代对象),count与repert不用接收可迭代对象作为输入

 

combinations(it, out_len)

把it产出的out_len个元素组合在一起,然后产出。

 

combinations_with_replacement(it, outlen)

把it产出的out_len个元素组合在一起,然后产出,包含相同元素的组合。

In [218]: list(combinations('abc',2))                                                                
Out[218]: [('a', 'b'), ('a', 'c'), ('b', 'c')]

In [219]: list(combinations_with_replacement('abc',2))                                               
Out[219]: [('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')]

 permutations(it, out_len=None)

把it产出的out_len个元素排列在一起,然后产出。

In [220]: list(permutations('abc',2))                                                                
Out[220]: [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')]

In [221]: list(product('abc',repeat=2))                                                              
Out[221]: 
[('a', 'a'),
 ('a', 'b'),
 ('a', 'c'),
 ('b', 'a'),
 ('b', 'b'),
 ('b', 'c'),
 ('c', 'a'),
 ('c', 'b'),
 ('c', 'c')]

In [222]:     

 

cycle(it)

从it中产出各个元素,存储各个元素的副本,然后按顺序重复不断地产出各个元素。

In [236]: c = cycle('ok')                                                                            

In [237]: next(c)                                                                                    
Out[237]: 'o'

In [238]:                                                                                            

In [238]: next(c)                                                                                    
Out[238]: 'k'

In [239]: next(c)                                                                                    
Out[239]: 'o'

In [240]: next(c)                                                                                    
Out[240]: 'k'

In [241]:     

 

 

count(start=0,step=1)      不需要接收可迭代元素作为参数

从start开始不断产出数字,按step指定的步幅增加

In [225]: c = count()                                                                                

In [226]: next(c)                                                                                    
Out[226]: 0

In [227]: next(c)                                                                                    
Out[227]: 1

In [228]: next(c)                                                                                    
Out[228]: 2

In [229]: c = count(3,0.1)                                                                           

In [230]: next(c)                                                                                    
Out[230]: 3

In [231]: next(c)                                                                                    
Out[231]: 3.1

In [232]: next(c)                                                                                    
Out[232]: 3.2

In [233]: next(c)                                                                                    
Out[233]: 3.3000000000000003

In [234]: next(c)                                                                                    
Out[234]: 3.4000000000000004

In [235]: next(c)                                                                                    
Out[235]: 3.5000000000000004

 

repert(item,[times])    不需要接收可迭代元素作为参数

重复不断产出指定的元素,除非提供times指定次数。

In [241]: r = repeat(3,2)                                                                            

In [242]: next(r)                                                                                    
Out[242]: 3

In [243]: next(r)                                                                                    
Out[243]: 3

In [244]: next(r)                                                                                    
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-244-8ebe59a56b1d> in <module>
----> 1 next(r)

StopIteration: 

In [245]: list(map(mul, range(10),repeat(5,3)))                                                      
Out[245]: [0, 5, 10]

In [246]:  

 

用于重新排列元素的生成器函数。

groupby(it,key=None)       (先排好序)

产出由两个元素组成的元素,形式为(key,group),其中key是分组标准,group是生成器,用于产出分组里的元素。

默认的分组标准是相同的元素为一组,用==判断。

In [259]: s = ('123123123123')                                                                       

In [260]: list(groupby(s))                                                                           
Out[260]: 
[('1', <itertools._grouper at 0x10fd00250>),
 ('2', <itertools._grouper at 0x11050d550>),
 ('3', <itertools._grouper at 0x11050d8d0>),
 ('1', <itertools._grouper at 0x11050d4d0>),
 ('2', <itertools._grouper at 0x1101e9f90>),
 ('3', <itertools._grouper at 0x1101e92d0>),
 ('1', <itertools._grouper at 0x1101e9610>),
 ('2', <itertools._grouper at 0x1102ec6d0>),
 ('3', <itertools._grouper at 0x1105c3dd0>),
 ('1', <itertools._grouper at 0x1105c3fd0>),
 ('2', <itertools._grouper at 0x1105c3b50>),
 ('3', <itertools._grouper at 0x1105c3e10>)]

In [261]: s = sorted(s)                                                                              

In [262]: s                                                                                          
Out[262]: ['1', '1', '1', '1', '2', '2', '2', '2', '3', '3', '3', '3']

In [263]: list(groupby(s))                                                                           
Out[263]: 
[('1', <itertools._grouper at 0x10f8f21d0>),
 ('2', <itertools._grouper at 0x10f8f2090>),
 ('3', <itertools._grouper at 0x10f6dce50>)]

 

In [266]: for char, group in groupby(s): 
     ...:     print(char,'->',list(group)) 
     ...:                                                                                            
1 -> ['1', '1', '1', '1']
2 -> ['2', '2', '2', '2']
3 -> ['3', '3', '3', '3']

 

In [267]: animails = ['duck','eagle','rat','giraffe','bear','bat']                                   

In [268]: animails.sort(key=len)                                                                     

In [269]: animails                                                                                   
Out[269]: ['rat', 'bat', 'duck', 'bear', 'eagle', 'giraffe']

 

In [271]: for length,group in groupby(animails,key=len): 
     ...:     print(length,'->',list(group)) 
     ...:      
     ...:                                                                                            
3 -> ['rat', 'bat']
4 -> ['duck', 'bear']
5 -> ['eagle']
7 -> ['giraffe']

In [272]: for length,group in groupby(reversed(animails),key=len): 
     ...:     print(length,'->',list(group)) 
     ...:      
     ...:      
     ...:                                                                                            
7 -> ['giraffe']
5 -> ['eagle']
4 -> ['bear', 'duck']
3 -> ['bat', 'rat']

 

reversed(seq)内置

所有iteritools里面唯一一个不接受可迭代的对象,而只接受序列为参数的函数。

从后向前,倒序产出seq中的元素;seq必须是序列,或者是实现了__reversed__特殊方法的对象。

 

tee(it, n=2)    返回的是元祖,应该是唯一一个工具里面返回是元祖的。

产生一个由n个生成器组成的元祖,每个生成器用于单独产出输入的可迭代对象中的元素。

分神器,可以一个可迭代对象,产生多个该可迭代对象的生成器。

In [273]: s = tee('abc')                                                                             

In [274]: s                                                                                          
Out[274]: (<itertools._tee at 0x10fd67eb0>, <itertools._tee at 0x10c19daf0>)

In [275]: type(s)                                                                                    
Out[275]: tuple

In [276]: a,b=s                                                                                      

In [277]: next(a)                                                                                    
Out[277]: 'a'

In [278]: next(a)                                                                                    
Out[278]: 'b'

In [279]: next(a)                                                                                    
Out[279]: 'c'

In [280]: list(b)                                                                                    
Out[280]: ['a', 'b', 'c']

In [281]: list(zip(tee('abc')))                                                                      
Out[281]: [(<itertools._tee at 0x10fb79eb0>,), (<itertools._tee at 0x10d49c1e0>,)]

In [282]: list(zip(*tee('abc')))                                                                     
Out[282]: [('a', 'a'), ('b', 'b'), ('c', 'c')]

In [283]:   

 

刚发现,zip一个蛮好用的功能,能把一个可迭代元素,每个元素拆分成一个个独立的元祖:

In [283]: list(zip('hello'))                                                                         
Out[283]: [('h',), ('e',), ('l',), ('l',), ('o',)]
posted @ 2020-01-04 22:18  就是想学习  阅读(355)  评论(0编辑  收藏  举报