Python——itertools模块

简介

迭代器的特点是:惰性求值,即只有迭代至某一值时,才会计算。这一特点使得迭代器非常适合于遍历大文件等,避免一次性存储至内存。Python内置的itertools模块包含了用于产生不同类型迭代器的函数或类。本篇笔记简单记录下该模块能解决的问题。

组成

itertools模块提供的迭代器函数有以下几种类型。

  • 无限迭代器,生成一个无限序列;
  • 有限迭代器,接收一个或多个序列作为参数,进行组合、分组和过滤等;
  • 组合生成器,序列的排列,组合等。

无限迭代器

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

创建一个迭代器,生成从0开始,step为1的连续整数;
e.g.

1
2
3
4
5
6
7
8
from itertools import *
for i in izip(count(1), ['a', 'b', 'c']):
print i
'''
(1, 'a')
(2, 'b')
(3, 'c')
'''

itertools.cycle(iterable)

创建一个迭代器,对iterable中的元素反复执行循环操作;
e.g.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from itertools import *
i = 0
for item in cycle(['a', 'b', 'c']):
i += 1
if i == 10:
break
print (i, item)
'''
(1, 'a')
(2, 'b')
(3, 'c')
(4, 'a')
(5, 'b')
(6, 'c')
(7, 'a')
(8, 'b')
(9, 'c')
'''

itertools.repeat(object[, times])

创建一个迭代器,重复生成object,times指定重复次数。
e.g.

1
2
3
4
5
6
7
8
9
from itertools import *
for i in repeat('over-and-over', 4):
print i
'''
over-and-over
over-and-over
over-and-over
over-and-over
'''

有限迭代器

itertools.chain(*iterables)

接收多个可迭代对象作为参数,将它们『连接』起来,作为一个新的迭代器返回;
e.g.

1
2
3
4
5
6
7
8
9
10
from itertools import *
for i in chain([1, 2], ['a', 'b', 'c']):
print i
'''
1
2
a
b
c
'''

itertools.compress(data, selectors)

可用于对数据进行筛选,当 selectors 的某个元素为 true 时,则保留 data 对应位置的元素,否则去除;
e.g.

1
2
3
4
from itertools import *
list(compress('ABCDEF', [1, 1, 0, 1, 0, 1]))
# ['A', 'B', 'D', 'F']

itertools.dropwhile(predicate, iterable)

对于 iterable 中的元素,如果predicate(item)为true,则丢弃该元素,否则返回该项及所有后续项;
e.g.

1
2
3
from itertools import dropwhile
list(dropwhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
#[6, 2, 1]

itertools.groupby(iterable[, key])

用于对序列进行分组,iterable 是一个可迭代对象,keyfunc 是分组函数,用于对 iterable 的连续项进行分组,返回一个 (key, sub-iterator) 的迭代器。
e.g.

1
2
3
4
5
6
7
8
9
10
11
12
from itertools import groupby
data = ['a', 'bb', 'ccc', 'dd', 'eee', 'f']
for key, value_iter in groupby(data, len):
print(key,list(value_iter))
'''
1 : ['a']
2 : ['bb']
3 : ['ccc']
2 : ['dd']
3 : ['eee']
1 : ['f']
'''

itertools.ifilter(predicate, iterable)

将 iterable 中 function(item) 为 True的元素组成一个迭代器返回,如果 function 是 None,则返回 iterable 中所有计算为 True 的项。
e.g.

1
2
3
4
5
>>> from itertools import ifilter
>>> list(ifilter(lambda x: x < 6, range(10)))
[0, 1, 2, 3, 4, 5]
>>> list(ifilter(None, [0, 1, 2, 0, 3, 4]))
[1, 2, 3, 4]

itertools.islice(iterable, stop)

是切片选择,start 是开始索引,stop 是结束索引,step 是步长,start 和 step 可选。
e.g.

1
2
3
4
5
>>> from itertools import count, islice
>>> list(islice([10, 6, 2, 8, 1, 3, 9], 5))
[10, 6, 2, 8, 1]
>>> list(islice(count(), 6))
[0, 1, 2, 3, 4, 5]

itertools.imap(function, *iterables)

类似于map操作
e.g.

1
2
3
from itertools import imap
list(imap(str, [1, 2, 3, 4]))
# ['1', '2', '3', '4']

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

从iterable创建n个独立的迭代器,以元组的形式返回。
e.g.

1
2
3
4
5
6
7
8
9
10
>>> from itertools import tee
>>>
>>> tee('abcd') # n 默认为 2,创建两个独立的迭代器
(<itertools.tee object at 0x1049957e8>, <itertools.tee object at 0x104995878>)
>>>
>>> iter1, iter2 = tee('abcde')
>>> list(iter1)
['a', 'b', 'c', 'd', 'e']
>>> list(iter2)
['a', 'b', 'c', 'd', 'e']

itertools.takewhile(predicate, iterable)

如果 predicate(item) 为 true,则保留该元素,只要 predicate(item) 为 false,则立即停止迭代。
e.g.

1
2
3
>>> from itertools import takewhile
>>> list(takewhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
[1, 3]

itertools.izip(*iterables)

用于将多个可迭代对象对应位置的元素作为一个元组,将所有元组『组成』一个迭代器。
e.g.

1
2
3
4
5
6
>>> from itertools import izip
>>> for item in izip('ABCD', 'xy'):
... print item
...
('A', 'x')
('B', 'y')

izip_longestizip类似,
e.g.

1
2
3
4
5
6
7
>>> for item in izip_longest('ABCD', 'xy', fillvalue='-'):
... print item
...
('A', 'x')
('B', 'y')
('C', '-')
('D', '-')

组合生成器

itertools.product(*iterables[, repeat])

用于求多个可迭代对象的笛卡尔积,它跟嵌套的 for 循环等价。
e.g.

1
2
3
4
5
6
7
8
9
10
11
12
>>> from itertools import product
>>> for item in product('ABCD', 'xy'):
... print item
...
('A', 'x')
('A', 'y')
('B', 'x')
('B', 'y')
('C', 'x')
('C', 'y')
('D', 'x')
('D', 'y')

itertools.permutations(iterable[, r])

生成一个排列,r指定生成排列的元素的长度,未指定,则默认为iterable长度。
e.g.

1
2
3
4
5
>>> from itertools import permutations
>>> list(permutations('ABC', 2))
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
>>> list(permutations('ABC'))
[('A', 'B', 'C'), ('A', 'C', 'B'), ('B', 'A', 'C'), ('B', 'C', 'A'), ('C', 'A', 'B'), ('C', 'B', 'A')]

itertools.combinations(iterable, r)

求序列的组合,r指定生成组合元素长度
e.g.

1
2
3
>>> from itertools import combinations
>>> list(combinations('ABC', 2))
[('A', 'B'), ('A', 'C'), ('B', 'C')]

combinations_with_replacementcombinations 类似,但它生成的组合包含自身元素。
e.g.

1
2
3
>>> from itertools import combinations_with_replacement
>>> list(combinations_with_replacement('ABC', 2))
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]

分享