Itertools模块官方描述:
Functional tools for creating and using iterators.即用于创建高效迭代器的函数。
itertools用于高效循环的迭代函数集合。
迭代器
迭代器(生成器) 在Python中是一种很常用也很好用的数据结构,比起列表(list)来说,迭代器最大的优势就是延迟计算,按需使用,从而提高开发体验和运行效率,以至于在Python 3中map,filter等操作返回的不再是列表而是迭代器。
话虽这么说但大家平时用到的迭代器大概只有range
了,而通过iter函数把列表对象转化为迭代器对象又有点多此一举,这时候我们今天的主角itertools就该上场了。
迭代器的特点
惰性求值(Lazy evaluation),即只有当迭代至某个值时,它才会被计算,这个特点使得迭代器特别适合于遍历大文件或无限集合等,因为我们不用一次性将它们存储在内存中。
使用itertools
itertools中的函数大多是返回各种迭代器对象,其中很多函数的作用我们平时要写很多代码才能达到,而在运行效率上反而更低,毕竟人家是系统库。
什么是itertools
itertools 模块包含了一系列用来产生不同类型迭代器的函数或类,这些函数的返回都是一个迭代器,我们可以通过 for 循环来遍历取值,也可以使用 next() 来取值。
itertools的分类
itertools 模块提供的迭代器函数有以下几种类型:
- 无限迭代器:生成一个无限序列,比如自然数序列 1, 2, 3, 4, …;
- 有限迭代器:接收一个或多个序列(sequence)作为参数,进行组合、分组和过滤等;
- 组合生成器:序列的排列、组合,求序列的笛卡儿积等;
无限迭代器
itertools 模块提供了三个函数(事实上,它们是类)用于生成一个无限序列迭代器:
函数 | 说明 |
count(firstval=0, step=1) | 创建一个从 firstval (默认值为 0) 开始,以 step (默认值为 1) 为步长的的无限整数迭代器 |
cycle(iterable) | 对 iterable 中的元素反复执行循环,返回迭代器 |
repeat(object [,times] | 反复生成 object,如果给定 times,则重复次数为 times,否则为无限 |
详解
1、itertools.count
就是一个计数器,可以指定起始位置和步长
##(1)参数不指定
# x= itertools.count()
# for i in x:
# if i > 6:
# break
# print(i)
## (2)指定开始值和步长
# x= itertools.count(2, 3)
# for i in x:
# if i > 6:
# break
# print(i)
##(3)也可用于切片操作:
# islice(iterable, [start, ] stop [, step])
# x = itertools.count(start=20, step=-1)
# print(list(itertools.islice(x, 0, 10, 1)))
2、itertools.cycle
循环指定的列表和迭代器,用于对 iterable 中的元素反复执行循环.
##(1)循环语句
cycle_strings = itertools.cycle('ABC')
i = 1
for string in cycle_strings:
if i == 10:
break
print(i, string)
i += 1
##(2)也可用于切片操作
x = itertools.cycle('ABC')
print(list(itertools.islice(x, 0, 10, 1)))
3、itertools.repeat
简单的生成一个拥有指定数目元素的迭代器
##(1)
x = itertools.repeat(3, 6)
print(list(x))
##(2)
for item in itertools.repeat('hello world', 3):
print(item)
有限迭代器
itertools 模块提供了多个函数(类),接收一个或多个迭代对象作为参数,对它们进行组合、分组和过滤等:
序号 | 函数 | 语法 | 说明 |
1 | chain() | chain(iterable1, iterable2, iterable3, …) | 连接多个列表或者迭代器,作为一个新的迭代器返回。 |
2 | compress() | compress(data, selectors) | 用于对数据进行筛选,当 selectors 的某个元素为 true 时,则保留 data 对应位置的元素,否则去除. |
3 | dropwhile() | dropwhile(predicate, iterable) | 按照真值函数丢弃掉列表和迭代器前面的元素,iterable 中的元素,如果 predicate(item) 为 true,则丢弃该元素,否则返回该项及所有后续项。 |
4 | groupby() | groupby(iterable[, keyfunc]) | iterable 是一个可迭代对象, keyfunc 是分组函数,用于对 iterable 的连续项进行分组,如果不指定,则默认对 iterable 中的连续相同项进行分组,返回一个 (key, sub-iterator) 的迭代器。 |
5 | islice() | islice(iterable, [start,] stop [, step]) | 切片选择,iterable 是可迭代对象,start 是开始索引,stop 是结束索引,step 是步长,start 和 step 可选。 |
6 | tee() | tee(iterable [,n]) | 用于从 iterable 创建 n 个独立的迭代器,以元组的形式返回,n 的默认值是 2。 |
7 | takewhile() | takewhile(predicate, iterable) | predicate(item) 为 true,则保留该元素,只要 predicate(item) 为 false,则立即停止迭代。 |
详解
1、itertools.chain
连接多个列表或者迭代器。
chain使用形式:
chain(iterable1, iterable2, iterable3, ...)
chain 接收多个可迭代对象作为参数,将它们【连接】起来,作为一个新的迭代器返回。
##(1)
x = itertools.chain(range(3), range(4), [3, 2, 4])
print(list(x))
##(2)
for item in itertools.chain([1, 2, 3], ['a', 'b', 'c']):
print(item)
2、itertools.compress
按照真值表筛选元素。
语法:compress(data, selectors)
当 selectors 的某个元素为 true 时,则保留 data 对应位置的元素,否则去除。
x = itertools.compress(range(5), (True, False, True, True, False))
print(list(x))
x1 = list(itertools.compress('ABCDEF', [1, 1, 0, 1, 0, 1]))
print(x1)
x2 = list(itertools.compress('ABCDEF', [1, 1, 0, 1]))
print(x2)
x3 = list(itertools.compress('ABCDEF', [True, False, True]))
print(x3)
3、itertools.dropwhile
按照真值函数丢弃掉列表和迭代器前面的元素
语法:dropwhile(predicate, iterable)
predicate 是函数,iterable 是可迭代对象。对于 iterable 中的元素,如果 predicate(item) 为 true,则丢弃该元素,否则返回该项及所有后续项。
x = itertools.dropwhile(lambda e: e < 5, range(10))
print(list(x))
x1 = list(itertools.dropwhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
print(x1)
x2 = list(itertools.dropwhile(lambda x2: x2 > 3, [2, 1, 6, 5, 4]))
print(x2)
---->
[5, 6, 7, 8, 9]
[6, 2, 1]
[2, 1, 6, 5, 4]
4、groupby
用于对序列进行分组。
语法:groupby(iterable[, keyfunc])
其中,iterable 是一个可迭代对象, keyfunc 是分组函数,用于对 iterable 的连续项进行分组,如果不指定,则默认对 iterable 中的连续相同项进行分组,返回一个 (key, sub-iterator) 的迭代器。
#(1)不指定分组
for key, value_iter in itertools.groupby('aaabbbaaccd'):
print(key, ":", list(value_iter))
#(2)指定分组--使用 len 函数作为分组函数,连续项不相同
data = ['a', 'bb', 'ccc', 'dd', 'eee', 'f']
for key, value_iter in itertools.groupby(data, len):
print(key, ":", list(value_iter))
#(3)指定分组--使用 len 函数作为分组函数,连续项相同
data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']
for key, value_iter in itertools.groupby(data, len):
print(key, ";", list(value_iter))
5、islice
切片选择
语法:islice(iterable, [start,] stop [, step])
iterable 是可迭代对象,start 是开始索引,stop 是结束索引,step 是步长,start 和 step 可选。
x = list(itertools.islice([10, 6, 2, 8, 1, 3, 9], 5))
print(x)
x1 = list(itertools.islice(itertools.count(), 6))
print(x1)
x2 = list(itertools.islice(itertools.count(), 3, 10))
print(x2)
x3 = list(itertools.islice(itertools.count(), 3, 10, 2))
print(x3)
---->
[10, 6, 2, 8, 1]
[0, 1, 2, 3, 4, 5]
[3, 4, 5, 6, 7, 8, 9]
[3, 5, 7, 9]
6、tee
生成指定数目的迭代器。
语法:tee(iterable [,n])
tee 用于从 iterable 创建 n 个独立的迭代器,以元组的形式返回,n 的默认值是 2。
#(1)n 默认为 2,创建2个独立的迭代器
x = itertools.tee('abcd')
print(x)
#(2)
x1, x2 = itertools.tee('abcde')
print(list(x1))
print(list(x2))
#(3)创建3个独立的迭代器
x3 = itertools.tee('abc', 3)
print(x3)
---->
(<itertools._tee object at 0x000001ABBD283108>, <itertools._tee object at 0x000001ABBD283148>)
['a', 'b', 'c', 'd', 'e']
['a', 'b', 'c', 'd', 'e']
(<itertools._tee object at 0x000001ABBD2832C8>, <itertools._tee object at 0x000001ABBD283308>, <itertools._tee object at 0x000001ABBD283348>)
(4)
x4 = itertools.tee(range(10), 3)
for num in x4:
print(list(num))
---->
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
7、takewhile
语法:takewhile(predicate, iterable)
predicate 是函数,iterable 是可迭代对象。如果 predicate(item) 为 true,则保留该元素,只要 predicate(item) 为 false,则立即停止迭代。
x = list(itertools.takewhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
print(x)
x1 = list(itertools.takewhile(lambda x: x > 3, [2, 1, 6, 5, 4]))
print(x1)
---->
[1, 3]
[]
组合生成器
itertools 组合生成器函数,用于求序列的排列、组合等:
序号 | 函数 | 语法 | 说明 |
1 | product | product(iter1, iter2, … iterN, [repeat=1]) | 用于求多个可迭代对象的笛卡尔积,它跟嵌套的 for 循环等价。repeat 是一个关键字参数,用于指定重复生成序列的次数。 |
2 | permutations | permutations(iterable[, r]) | 用于生成一个排列,r 指定生成排列的元素的长度,如果不指定,则默认为可迭代对象的元素长度。 |
3 | combinations | combinations(iterable, r) | 用于求序列的组合,r 指定生成组合的元素的长度。 |
4 | combinations_with_replacement | combinations_with_replacement(iterable, r) | 和 combinations 类似,但它生成的组合包含自身元素。 |
详解
1、product
product 用于求多个可迭代对象的笛卡尔积,它跟嵌套的 for 循环等价。
语法:product(iter1, iter2, ... iterN, [repeat=1])
repeat
是一个关键字参数,用于指定重复生成序列的次数,
for item in itertools.product('ABCD', 'xy'):
print(item)
x = list(itertools.product('ab', range(3)))
print(x)
x1 = list(itertools.product((0, 1), (0, 1), (0, 1)))
print(x1)
x2 = list(itertools.product('ABC', repeat=2))
print(x2)
2、permutations
permutations 用于生成一个排列。
语法:permutations(iterable[, r])
r 指定生成排列的元素的长度,如果不指定,则默认为可迭代对象的元素长度。
x1 = list(itertools.permutations('ABC', 2))
print(x1)
x2 = list(itertools.permutations('ABC'))
print(x2)
---->
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]
3、combinations 用于求序列的组合
语法:combinations(iterable, r)
其中,r 指定生成组合的元素的长度。
x = list(itertools.combinations('ABC', 2))
print(x)
---->
[('A', 'B'), ('A', 'C'), ('B', 'C')]
4、combinations_with_replacement
和 combinations 类似,但它生成的组合包含自身元素。
x = list(itertools.combinations_with_replacement('ABC', 2))
print(x)
---->
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
小结
itertools
模块提供了很多用于产生多种类型迭代器的函数,它们的返回值不是 list,而是迭代器。