itertools是python专为高效循环而创建的一组迭代器函数,用过的都说好。
itertools
中包有三个无穷迭代器,分别是count
, cycle
和repeat
,由于迭代器这种东西很难描述,所以直接看案例。唯一需要注意一点就是,千万别对无穷迭代器用list
。
>>> import itertools as it
>>> x = it.count(0,2) #两个参量分别是初始值和步长,
>>> next(x)
0
>>> for i in range(3): print(next(x),end=' ')
...
2 4 6
>>> x = it.count(3) #步长为可选参量,默认为1
>>> for i in range(3) : print(next(x),end=' ')
...
3 4 5
>>> for _ in range(10): print(next(x), end=' ')
...
6 7 8 9 10 11 12 13 14 15
其中,x的两个参量分别是初始值和步长,步长为可选参量,默认为1。
cycle的参数可以是列表元组或者是字符串。
>>> c = it.cycle([1,2,3]) #对1,2,3进行无穷的循环
>>> next(c)
1
>>> for i in range(10): print(next(c),end=' ')
...
2 3 1 2 3 1 2 3 1 2
>>> c = it.cycle("love") #其参数也可以为字符串
>>> for i in range(10): print(next(c), end=' ')
...
l o v e l o v e l o
一般来说,repeat有两个输入参数,一个是循环内容,第二个参数是循环次数。如果省略第二个参数,就表示无穷循环。
>>> r = it.repeat(10,3) #对10循环3次
>>> list(r)
[10, 10, 10]
>>> r = it.repeat(10) #如果只有一个参数,则无穷循环
>>> for i in range(10): print(next(r), end=' ')
...
10 10 10 10 10 10 10 10 10 10
>>> r = it.repeat([1,2],3)
>>> list(r)
[[1, 2], [1, 2], [1, 2]]
这类迭代器可以找到与之相似的python表达式,区别在于效率,毕竟itertools
是在底层实现的。
下表中,左侧为迭代器表达式,右侧为将这个迭代器转换为list
之后的形式,默认from itertools import *
。
accumulate(lst,func) | 累加求和 | |
chain(as,bs,…) | 列表连加器 | |
compress(d,s) | 根据s的真值取d | |
filterfalse(func,lst) | lst中func为假的元素 | |
dropwhile(func,lst) | lst中,自func为假之后的元素 | |
takewhile(func,lst) | lst中,自func为假之前的元素 | |
islice(lst,[s,]e,[,step]) | 索引 |
解释很无力,具体还是要看代码:
>>> from itertools import *
>>> from math import *
>>> lst = list(range(4,-4,-1))
>>> lst
[4, 3, 2, 1, 0, -1, -2, -3]
## accumulate 自左向右执行函数
>>> list(accumulate(lst)) #累加求和
[4, 7, 9, 10, 10, 9, 7, 4]
>>> list(accumulate(lst,max)) #自左向右取最大值
[4, 4, 4, 4, 4, 4, 4, 4]
>>> list(accumulate(lst,min)) #自左向右取最小值
[4, 3, 2, 1, 0, -1, -2, -3]
## chain,相当于[*lst,*lst]
>>> list(chain(lst,lst))
[4, 3, 2, 1, 0, -1, -2, -3, 4, 3, 2, 1, 0, -1, -2, -3]
>>> [*lst,*lst]
[4, 3, 2, 1, 0, -1, -2, -3, 4, 3, 2, 1, 0, -1, -2, -3]
## compress
>>> flags = [i>0 for i in lst]
>>> flags
[True, True, True, True, False, False, False, False]
>>> list(compress(lst,flags))
[4, 3, 2, 1]
## filterfalse
>>> isNeg = lambda x : x<0
>>> list(filterfalse(isNeg,lst))
[4, 3, 2, 1, 0]
## dropwhile
>>> isOdd = lambda x : not x%2 #如果为偶数则返回True
>>> list(dropwhile(isOdd,lst)) #3是奇数,从而返回自3之后的值
[3, 2, 1, 0, -1, -2, -3]
## takewhile
>>> isPos = lambda x : x>0
>>> list(takewhile(isPos,lst)) #输出isPos为假之前的内容
[4, 3, 2, 1]
## islice
>>> list(islice(lst,3))
[4, 3, 2] # 等于lst[:3]
>>> list(islice(lst,1,3))
[3, 2] # 等于lst[1:3]
>>> list(islice(lst,0,6,2))
[4, 2, 0] # 等于lst[0:6:2]
## pairwise(lst),相当于zip(lst[:-1],lst[1:])
>>> list(pairwise(lst))
[(4, 3), (3, 2), (2, 1), (1, 0), (0, -1), (-1, -2), (-2, -3)]
>>> list(zip(lst[:-1],lst[1:]))
[(4, 3), (3, 2), (2, 1), (1, 0), (0, -1), (-1, -2), (-2, -3)]
## zip_longest,按照最长的序列进行zip,不足补充fillvalue
>>> list(zip_longest(lst[:3],lst[:2],fillvalue=0))
[(4, 4), (3, 3), (2, 0)]
其中,pairwise(lst),相当于zip(lst[:-1],lst[1:]);zip_longest,按照最长的序列进行zip,不足补充fillvalue。
product是笛卡尔积,换言之就是两列参数中一对一的组合。通过product,可以替代嵌套的for循环。
permutations 输入序列的多次组合,每个组合中不得有重复元素;combinations 在permutations的基础上,要求元组有序;combinations_with_replacement 则是元素可重复的combination
## product 笛卡尔积
>>> lst = list(range(4))
>>> lst
[0, 1, 2, 3]
>>> list(product(lst,lst))
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1), (3, 2), (3, 3)]
## product 可以用来替代嵌套的for循环
>>> list(product(lst,lst))
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (1, 3), (2, 0), (2, 1), (2, 2), (2, 3), (3, 0), (3, 1), (3, 2), (3, 3)]
>>> for i,j in product(lst,lst):
... print(i,j,end=';')
...
0 0;0 1;0 2;0 3;1 0;1 1;1 2;1 3;2 0;2 1;2 2;2 3;3 0;3 1;3 2;3 3;
>>> list(permutations(lst,2))
[(0, 1), (0, 2), (0, 3), (1, 0), (1, 2), (1, 3), (2, 0), (2, 1), (2, 3), (3, 0), (3, 1), (3, 2)]
# combinations 在permutations的基础上,要求元组有序
>>> list(combinations(lst,2))
[(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)]
## combinations_with_replacement 元素可重复的combination
>>> list(combinations_with_replacement(lst,2))
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
## groupby 返回迭代地址
>>> for k, g in groupby(lst):
... print(k,list(g))
...
0 [0] #其中k为lst中的值;g为该值生成的迭代器
1 [1] #通过list将g这个迭代器又转化为了list
2 [2]
3 [3]
## starmap 输入为函数和列表(可迭代变量),要求列表的每个元素都是列表,然后取出列表中的值执行
>>> list(starmap(lambda x:-x, [[x] for x in lst]))
[0, -1, -2, -3]
>>> list(starmap(lambda x,y:x+y, list(product(lst,lst))))
[0, 1, 2, 3, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6]