欢迎来到田晓东的博客

人生三从境界:昨夜西风凋碧树,独上高楼,望尽天涯路。 衣带渐宽终不悔,为伊消得人憔悴。 众里寻他千百度,蓦然回首,那人却在灯火阑珊处。
扩大
缩小

python itertools模块

1、创建属于自己的迭代器,实现遍历
2、快速&节约内存

无限迭代器:

count
cycle
repeat

count返回一系列值,以start参数开始,也可以接受step参数

无step方式:

from itertools import count

for i in count(10):
    if i>20:
        break
    else:
        print(i)

结果为:10 11 12 13 14 15 16 17 18 19 20

有step方式:

from itertools import count,islice:

for i in islice(count(10),10):
    print(i)

结果为:10 11 12 13 14 15 16 17 18 19
解析:count从10开始,迭代10次后停止

cycle迭代器可实现在序列上创建无限循环的迭代器

用计数的方式实现有限迭代:

from itertools import cycle
count =0
for item in cycle("ABCDEFG"):
    if count >20:
        break
    else:
        print(item)
        count+=1

结果为:A B C D E F G A B C D E F G A B C D E F G
解析:cycle("ABCDEFG")会生成一个由"A" "B" "C" "D" "E" "F" "G"组成的无限循环迭代器,可实现遍历

用python内置next()函数实现遍历迭代

from itertools import cycle
list1=["A","B","C","D","E","F","G"]
iterator=cycle(list1)
for i in range(20):
    print(next(iterator))

结果为:A B C D E F G A B C D E F G A B C D E F
解析:cycle("ABCDEFG")会生成一个由"A" "B" "C" "D" "E" "F" "G"组成的无限循环迭代器,
每次调用next()函数会返回迭代器中的下一个值

repeat迭代器返回同一个对象,如不设定次数会无限迭代

指定迭代次数:

from itertools import repeat
iterator=repeat("txd",5)
for i in range(6):
    print(next(iterator))

结果:txd txd txd txd txd
第六次执行迭代next()方法时报错:
Traceback (most recent call last):
File "D:\unitest\exercise\排序.py", line 4, in <module>
    print(next(iterator))
StopIteration

解析:由于指定了迭代次数为5,循环执行到第6次时会报错

不指定迭代次数:

from itertools import repeat
iterator=repeat("txd")
for i in range(20):
    print(next(iterator))
结果:txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd txd

有限迭代器

accumulate迭代器返回累加之和或两个函数的累计结果

返回迭代器每对象被累加之和:
from itertools import accumulate
print(list(accumulate(range(20))))
结果:[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190]
解析:第一个是0,第二个是0+1,第三个是1+2,等等;用内置的list方法,为了可读性强,否则仅仅打印出迭代器对象

返回迭代器对象被operator.mul函数相乘之积:
from itertools import accumulate
import operator
print(list(accumulate(range(1,20),operator.mul)))

结果:[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 121645100408832000]
解析:第一个是1,第二个是1*2,第三个是2*3,等等;用内置的list方法,为了可读性强,否则仅仅打印出迭代器对象

chain迭代器将一系列可迭代对象平铺为一个长的可迭代对象

使用chain完成迭代器合并:

from itertools import chain

list1=[1,2,3,4,5]
list2=['a','b','c','d','e']
list3=['ls','cd','mv','/home','/usr']
fn_list=list(chain(list1,list2,list3))
print(fn_list)
结果:[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e', 'ls', 'cd', 'mv', '/home', '/usr']
    list1地址为:1921345868416;fn_list地址为1921348731392
解析:将可迭代对象传入chain迭代器中;用内置的list方法,为了可读性强,否则仅仅打印出迭代器对象

另一种方式,直接使用列表的添加:
list1=[1,2,3,4,5]
list2=['a','b','c','d','e']
list3=['ls','cd','mv','/home','/usr']
fn_list=list1+list2+list3
print(fn_list)
print("list1地址为:{0};fn_list地址为{1}".format(id(list1),id(list2)))

结果:[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e', 'ls', 'cd', 'mv', '/home', '/usr']
    list1地址为:1921348872640;fn_list地址为1921345868416

使用chain里from_iterable()方法,与chain不同的是,需要传递一个嵌套的列表

from itertools import chain

list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c', 'd', 'e']
list3 = ['ls', 'cd', 'mv', '/home', '/usr']
print(list(chain.from_iterable(list1,list2,list3)))
结果:
Traceback (most recent call last):
File "D:\unitest\exercise\排序.py", line 6, in <module>
print(chain.from_iterable(list1,list2,list3))
TypeError: chain.from_iterable() takes exactly one argument (3 given)

正确方式为:
from itertools import chain

list1 = [1, 2, 3, 4, 5]
list2 = ['a', 'b', 'c', 'd', 'e']
list3 = ['ls', 'cd', 'mv', '/home', '/usr']
print(list(chain.from_iterable([list1,list2,list3])))
结果为:[1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e', 'ls', 'cd', 'mv', '/home', '/usr']

compress子模块可实现迭代器过滤,传入两个迭代器,通过第二个迭代器的布尔表达式判断进行筛选

from itertools import compress
list1=[1,2,3,4,5,5]
list2=[True,False,False,True]
print(list(compress(list1,list2)))
结果:[1, 4]

dropwhile

from itertools import dropwhile
list1=[1,2,3,4,5,6,7,8,9,10,9,8,7]
print(list(dropwhile(lambda x:x < 10,list1)))

结果:[10, 9, 8, 7]

from itertools import dropwhile
list1=[1,2,3,4,5,6,7,8,9,10,11,10,9,8,7]
print(list(dropwhile(lambda x:x > 10,list1)))

结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 10, 9, 8, 7]
解析:dropwhile内部判断一旦为false,则获得该迭代对象及它之后的元素

talkwhile 与dropwhile 刚好相反,遇到条件为False时,忽略可迭代对象中剩余的元素

filterfalse 只返回判断为false的值

from itertools import filterfalse
list1=[1,2,3,4,5,6,7,8,9,10,11,20,21,22,23,23,35,562,10,9,8,7]
print(list(filterfalse(lambda x:x > 10,list1)))

结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7]

groupby 迭代器返回迭代器对象中连续的keys和groups

传入groupby 的为排序后的迭代器
from itertools import groupby

vehicles =[('Ford','Taurus'),('Dodge','Durango'),('Chevrolet','Cobalt'),('Ford','F150'),('Dodge','Charger'),('Ford','GT')]
sorted_vehicles =sorted(vehicles)
for key ,group in groupby(sorted_vehicles,lambda make:make[0]):
    for make ,model in group:
        print("{model} is made by {make}".format(model=model,make=make))
    print("------ End of Group-----")

结果:
Cobalt is made by Chevrolet
***** End of Group *****

Charger is made by Dodge
Durango is made by Dodge
***** End of Group *****

F150 is made by Ford
GT is made by Ford
Taurus is made by Ford
***** End of Group *****

传入groupby的非排序后的迭代器:

from itertools import groupby

vehicles =[('Ford','Taurus'),('Dodge','Durango'),('Chevrolet','Cobalt'),('Ford','F150'),('Dodge','Charger'),('Ford','GT')]

for key ,group in groupby(vehicles,lambda make:make[0]):
    for make ,model in group:
        print("{model} is made by {make}".format(model=model,make=make))
    print("------ End of Group-----")

结果为:
Taurus is made by Ford
------ End of Group-----
Durango is made by Dodge
------ End of Group-----
Cobalt is made by Chevrolet
------ End of Group-----
F150 is made by Ford
------ End of Group-----
Charger is made by Dodge
------ End of Group-----
GT is made by Ford
------ End of Group-----

islice从迭代对象中返回选择元素的迭代器

itertools.islice(iterable,stop)方式

from itertools import islice
print(list(islice([1,2,3,4,5,6,7,8],4)))
结果:[1, 2, 3, 4]

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

from itertools import islice
print(list(islice([1,2,3,4,5,6,7,8,9],4,9)))
结果:[5, 6, 7, 8, 9]

starmap会创建一个新迭代器,与map()区别是:map()传入的函数是function(*c),starmap()传入的是function(a,b)

from itertools import starmap

def add_f(a,b):
    return a+b
for item in starmap(add_f,[(1,3),(5,8),(9,100)]):
    print(item)

结果:
4
13
109

tee 实现从一个迭代器中创建多个迭代器

from itertools import tee

list1=[1,2,3,4,5,6]
iter1,iter2=tee(list1)
print(list(iter1))
print(list(iter2))

结果:
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6]

zip_longest 将两个迭代对象打包在一起,如果可迭代对象长度不同,可以传入fillvalue

from itertools import zip_longest

A=['a','b','c','d']
B=[1,2,3,4,5,6,7,8,9]
new_tup=zip_longest(A,B,fillvalue='BLANK')
print(list(new_tup))

组合产生器

combinations 从一个迭代器中创建一个迭代器,迭代器元素相同(按长度进行组合的新迭代对象),不会创建重复的组合

from itertools import combinations
A = 'txdT'
new_iter=combinations(A,2)
for item in new_iter:
    print(''.join(item))
    print(item)
结果:
tx
('t', 'x')
td
('t', 'd')
tT
('t', 'T')
xd
('x', 'd')
xT
('x', 'T')
dT
('d', 'T')

combinations_with_replacement 在combinations基础上加(tt,xx,dd,TT)

permutations 在combinations基础上加(xt,dt,Tt,dx,Tx,Td)

product 从输入中创建笛卡尔积

from itertools import  product

A=[('A','B'),(1,2),("大","小")]
new_dke=product(*A)
print(list(new_dke))

结果:[('A', 1, '大'), ('A', 1, '小'), ('A', 2, '大'), ('A', 2, '小'), ('B', 1, '大'), ('B', 1, '小'), ('B', 2, '大'), ('B', 2, '小')]

posted on 2022-02-25 16:04  匍匐的仰望者  阅读(122)  评论(0编辑  收藏  举报

导航