高效的 itertools 模块
itertools
库
迭代器的特点是:惰性求值(Lazy evaluation
),即只有当迭代至某个值时,它才会被计算,这个特点使得迭代器特别适合于遍历大文件或无限集合等,因为我们不用一次性将它们存储在内存中。
Python 内置的 itertools 模块包含了一系列用来产生不同类型迭代器的函数或类,这些函数的返回都是一个迭代器,我们可以通过 for 循环来遍历取值,也可以使用next()
来取值。
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,count
count() 接收两个参数,第一个参数指定开始值,默认为 0,第二个参数指定步长,默认为 1:
>>> import itertools
>>>
>>> nums = itertools.count()
>>> for i in nums:
... if i > 6:
... break
... print i
...
0
1
2
3
4
5
6
>>> nums = itertools.count(10, 2) # 指定开始值和步长
>>> for i in nums:
... if i > 20:
... break
... print i
...
10
12
14
16
18
20
2,cycle
cycle() 用于对 iterable 中的元素反复执行循环:
>>> import itertools
>>>
>>> cycle_strings = itertools.cycle('ABC')
>>> i = 1
>>> for string in cycle_strings:
... if i == 10:
... break
... print i, string
... i += 1
...
1 A
2 B
3 C
4 A
5 B
6 C
7 A
8 B
9 C
3,repeat
repeat() 用于反复生成一个 object:
>>> import itertools
>>>
>>> for item in itertools.repeat('hello world', 3):
... print item
...
hello world
hello world
hello world
>>>
>>> for item in itertools.repeat([1, 2, 3, 4], 3):
... print item
...
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
有限迭代器
itertools 模块
提供了多个函数(类),接收一个或多个迭代对象作为参数,对它们进行组合
、分组
和过滤
等:
1,chain
chain 的使用形式如下:
chain(iterable1, iterable2, iterable3, ...)chain 接收多个可迭代对象作为参数,将它们『连接』起来,作为一个新的迭代器返回。
>>> from itertools import chain
>>>
>>> for item in chain([1, 2, 3], ['a', 'b', 'c']):#chain([1, 2, 3], ['a', 'b', 'c'])==[1, 2, 3, 'a', 'b', 'c']
... print item
...
1
2
3
a
b
c
2,compress
compress 的使用形式如下:
compress(data, selectors)compress 可用于对数据进行筛选,当 selectors 的某个元素为 true 时,
则保留 data 对应位置的元素,否则去除:
>>> from itertools import compress
>>>
>>> list(compress('ABCDEF', [1, 1, 0, 1, 0, 1]))
['A', 'B', 'D', 'F']
>>> list(compress('ABCDEF', [1, 1, 0, 1]))
['A', 'B', 'D']
>>> list(compress('ABCDEF', [True, False, True]))
['A', 'C']
3,dropwhile
dropwhile 的使用形式如下:
dropwhile(predicate, iterable)其中,predicate 是函数,iterable 是可迭代对象。
对于 iterable 中的元素,如果 predicate(item) 为 true,则丢弃该元素,
**否则返回该项及所有后续项**。
>>> from itertools import dropwhile
>>>
>>> list(dropwhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
#返回6及6后面的item
[6, 2, 1]
>>>
>>> list(dropwhile(lambda x: x > 3, [2, 1, 6, 5, 4]))
[2, 1, 6, 5, 4]
4,groupby
groupby 用于对序列进行分组,它的使用形式如下:
groupby(iterable[, keyfunc])其中,iterable 是一个可迭代对象,keyfunc 是分组函数,用于对 iterable 的连续项进行分组,
如果不指定,则默认对 iterable 中的连续相同项进行分组,
返回一个 (key, sub-iterator) 的迭代器。
>>> from itertools import groupby
>>>
>>> for key, value_iter in groupby('aaabbbaaccd'):
... print key, ':', list(value_iter)
...
a : ['a', 'a', 'a']
b : ['b', 'b', 'b']
a : ['a', 'a']
c : ['c', 'c']
d : ['d']
>>>
>>> data = ['a', 'bb', 'ccc', 'dd', 'eee', 'f']
>>> for key, value_iter in groupby(data, len): # 使用 len 函数作为分组函数
... print key, ':', list(value_iter)
...
1 : ['a']
2 : ['bb']
3 : ['ccc']
2 : ['dd']
3 : ['eee']
1 : ['f']
>>>
>>> data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']
>>> for key, value_iter in groupby(data, len):
... print key, ':', list(value_iter)
...
1 : ['a']
2 : ['bb', 'cc']
3 : ['ddd', 'eee']
1 : ['f']
5,ifilter
, ifilterfalse
ifilter 的使用形式如下:
ifilter(function or None, sequence)
将 iterable 中 function(item) 为 True 的元素组成一个迭代器返回,
如果 function 是 None,则返回 iterable 中所有计算为 True 的项。
>>> 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]
ifilterfalse
的使用形式和ifilter
类似,它将 iterable 中 function(item) 为 False 的元素组成一个迭代器返回,如果 function 是 None,则返回 iterable 中所有计算为 False 的项。
>>> from itertools import ifilterfalse
>>>
>>> list(ifilterfalse(lambda x: x < 6, range(10)))
[6, 7, 8, 9]
>>>
>>> list(ifilter(None, [0, 1, 2, 0, 3, 4]))
[0, 0]
6,islice
islice 是切片选择,它的使用形式如下:
islice(iterable, [start,] stop [, step])其中,iterable 是可迭代对象,start 是开始索引
,stop 是结束索引,step 是步长,start 和 step 可选。
>>> 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]
>>>
>>> list(islice(count(), 3, 10))
[3, 4, 5, 6, 7, 8, 9]
>>> list(islice(count(), 3, 10 ,2))
[3, 5, 7, 9]
使用 islice
实现循环内隔行处理
可能是为了美观,在这份文件里的每两个标题之间,都有一个 “---
” 分隔符。现在,我们需要获取文件里所有的标题列表,所以在遍历文件内容的过程中,必须跳过这些无意义的分隔符。
我们可以通过在循环内加一段基于当前循环序号的 if 判断来做到这一点:
但对于这类在循环内进行隔行处理的需求来说,如果使用 itertools
里的 islice()
函数修饰被循环对象,可以让循环体代码变得更简单直接。
islice(seq,start,end,step)
函数和数组切片操作( list[start:stop:step]
)有着几乎一模一样的参数。如果需要在循环内部进行隔行处理的话,只要设置第三个递进步长参数 step
值为 2 即可(默认为 1)。
7,imap
imap 类似 map 操作,它的使用形式如下:
有一份包含 Reddit 帖子标题的外部数据文件,里面的内容格式是这样的:
imap(func, iter1, iter2, iter3, ...)imap 返回一个迭代器,元素为 func(i1, i2, i3, ...),i1,i2 等分别来源于 iter, iter2
>>> from itertools import imap
>>>
>>> imap(str, [1, 2, 3, 4])
<itertools.imap object at 0x10556d050>
>>>
>>> list(imap(str, [1, 2, 3, 4]))
['1', '2', '3', '4']
>>>
>>> list(imap(pow, [2, 3, 10], [4, 2, 3]))
[16, 9, 1000]
8,tee
tee 的使用形式如下:
tee(iterable [,n])
tee 用于从 iterable 创建 n 个独立的迭代器,以元组的形式返回,n 的默认值是 2。
>>> 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']
>>>
>>> tee('abc', 3) # 创建三个独立的迭代器
(<itertools.tee object at 0x104995998>, <itertools.tee object at 0x1049959e0>, <itertools.tee object at 0x104995a28>)
8,takewhile
takewhile 的使用形式如下:
takewhile(predicate, iterable)其中,predicate 是函数,iterable 是可迭代对象。
对于 iterable 中的元素,如果 predicate(item) 为 true,则保留该元素,
只要 predicate(item) 为 false,则立即停止迭代。
>>> from itertools import takewhile
>>>
>>> list(takewhile(lambda x: x < 5, [1, 3, 6, 2, 1]))
[1, 3]
>>> list(takewhile(lambda x: x > 3, [2, 1, 6, 5, 4]))
[]
使用takewhile
替代break 语句
有时,我们需要在每次循环开始时,判断循环是否需要提前结束。比如下面这样:
for uer in users:# 当第一个不合格的用户出现后,不再进行后面的处理if not is_qualified(user):break#进行处理... ...
对于这类需要提前中断的循环,我们可以使用 takewhile() 函数
来简化它。takewhile(predicate,iterable)
会在迭代 iterable
的过程中不断使用当前对象作为参数调用predicate 函数
并测试返回结果,如果函数返回值为真,则生成当前对象,循环继续。否则立即中断当前循环。
from itertools import takewhilefor user in takewhile(is_qualified, users):# 进行处理... ...
8,izip
, izip_longest
izip 用于将多个可迭代对象对应位置的元素作为一个元组,将所有元组『组成』一个迭代器,并返回。它的使用形式如下:
izip(iter1, iter2, ..., iterN)
如果某个可迭代对象不再生成值,则迭代停止。
>>> from itertools import izip
>>>
>>> for item in izip('ABCD', 'xy'):
... print item
...
('A', 'x')
('B', 'y')
>>> for item in izip([1, 2, 3], ['a', 'b', 'c', 'd', 'e']):
... print item
...
(1, 'a')
(2, 'b')
(3, 'c')
izip_longest
跟 izip
类似,但迭代过程会持续到所有可迭代对象的元素都被迭代完。它的形式如下:
izip_longest(iter1, iter2, ..., iterN, [fillvalue=None])
如果有指定 fillvalue,则会用其填充缺失的值,否则为 None。
>>> from itertools import izip_longest
>>>
>>> for item in izip_longest('ABCD', 'xy'):
... print item
...
('A', 'x')
('B', 'y')
('C', None)
('D', None)
>>>
>>> for item in izip_longest('ABCD', 'xy', fillvalue='-'):
... print item
...
('A', 'x')
('B', 'y')
('C', '-')
('D', '-')
组合生成器
itertools 模块还提供了多个组合生成器函数,用于求序列的排列、组合等:
1,product
product 用于求多个可迭代对象的笛卡尔积,它跟嵌套的 for 循环等价。它的一般使用形式如下:
product(iter1, iter2, ... iterN, [repeat=1])
其中,repeat 是一个关键字参数,用于指定重复生成序列的次数,
>>> 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')
>>>
>>> list(product('ab', range(3)))
[('a', 0), ('a', 1), ('a', 2), ('b', 0), ('b', 1), ('b', 2)]
>>>
>>> list(product((0,1), (0,1), (0,1)))
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
>>>
>>> list(product('ABC', repeat=2))
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]
>>>
使用 product 扁平化多层嵌套循环
虽然我们都知道“扁平的代码比嵌套的好”。但有时针对某类需求,似乎一定得写多层嵌套循环才行。比如下面这段:
def find_twelve(num_list1, num_list2, num_list3):'''从 3 个数字列表中,寻找是否存在和为 12 的 3 个数'''for num1 in num_list1:for num2 in num_list2:for num3 in num_list3:if num1 + num2 + num3 == 12:return num1, num2, num3
对于这种需要嵌套遍历多个对象的多层循环代码,我们可以使用 product() 函数
来优化它。product()
可以接收多个可迭代对象,然后根据它们的笛卡尔积不断生成结果。
from itertools import productdef find_twelve_v2(num_list1, num_list2, num_list3):for num1, num2, num3 in product(num_list1, num_list2, num_list3):if num1 + num2 + num3 == 12:return num1, num2, num3
相比之前的代码,使用 product()
的函数只用了一层 for 循环就完成了任务,代码变得更精炼了。
2,permutations
permutations 用于生成一个排列,它的一般使用形式如下:
permutations(iterable[, r])
其中,r 指定生成排列的元素的长度,如果不指定,则默认为可迭代对象的元素长度。
>>> from itertools import permutations
>>>
>>> permutations('ABC', 2)
<itertools.permutations object at 0x1074d9c50>
>>>
>>> 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')]
>>>
3,combinations
combinations 用于求序列的组合,它的使用形式如下:
combinations(iterable, r)
其中,r 指定生成组合的元素的长度。
>>> from itertools import combinations
>>>
>>> list(combinations('ABC', 2))
[('A', 'B'), ('A', 'C'), ('B', 'C')]
combinations_with_replacement
和combinations
类似,但它生成的组合包含自身元素。
>>> from itertools import combinations_with_replacement
>>>
>>> list(combinations_with_replacement('ABC', 2))
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
4,itertools.accumulate
简单来说就是累加。
from itertools import accumulate
x = accumulate(range(10))
print(list(x))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
高效的 itertools 模块相关推荐
- python itertools模块位置_Python高效编程之itertools模块详解
0 前言 说到处理循环,我们习惯使用for, while等,比如依次打印每个列表中的字符:lis = [ I , love , python ] for i in lis: print(i) I lo ...
- python itertools模块chain函数功能详解 itertools.chain(*iterable)
Itertools模块, itertools提供了高效快捷的用于操作迭代对象的函数.通过使用这个模块,可以简化代码. Itertools.chain语法 Itertools.chain(*iterab ...
- Python 的 itertools 模块
Python 当中的 itertools 模块在程序员中的存在感一直不高,可能是大家真正用到的时候并不多.然而,最近它却成功引起了我的注意,它在 Python 求列表的所有 k 阶子列 时大放异彩,所 ...
- itertools模块
Python-进阶-itertools模块小结 Python-进阶-itertools模块小结 组成 第一部分 itertools.count(start=0, step=1) itertools.c ...
- python itertools模块详解
目录 简介 无穷迭代器 count() cycle() repeat() 有限迭代器 chain() groupby() accumulate() 组合迭代器 product() permutatio ...
- Pyhton 内置 itertools 模块chain、accumulate、compress、drop、take等函数使用
Python 内置的 itertools 模块使用了 yield 生成器. 1. chain 拼接迭代器 chain 函数实现元素拼接,原型如下,参数 * 表示可变的参数: chain(*iterab ...
- python自带intertool模块找不到_Python itertools模块:生成迭代器(示例分析)
1 itertools 模块中主要包含了一些用于生成迭代器的函数.在 Python 的交互式解释器中先导入 itertools 模块,然后输入 e for e in dir(itertools) if ...
- python自带intertool模块找不到_介绍Python中内置的itertools模块
Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. 首先,我们看看itertools提供的几个"无限"迭代器: >>> import ...
- Python itertools模块
今天学了简单好玩的模块.itertools模块,简单的说,itertools模块就是产生一个循环器 来看下这个模块的功能都有哪些吧 无穷循环器 count() 从開始的数字一直数下去 count(1 ...
最新文章
- 如果不是为了面试,AI工程师刷题有用吗?
- JAVA一个项目的路径为_java 得到项目路径
- 记录一下halcon例程报错和两个视觉库感兴趣区域绘制
- 用真实脑电波提高魔法伤害!硬核玩家改造《上古卷轴V》,脑机接口控制魔法施放...
- 百度2011大会见闻:百度开始推出耀主页
- python测试用例管理模块_python-selenium并发执行测试用例(方法一 各模块每一条并发执行)...
- WebP 在减少图片体积和流量上的效果如何?—— WebP 技术实践分享
- Asp.net MVC在Razor中输出Html的两种方式
- [转载] Java中的final变量、final方法和final类
- c++ string类_C++|细说STL string类概貌及底层细节
- Linux CTF 逆向入门
- LaTex使用的一些技巧记录
- Microsoft.Windows.Controls.Ribbon.RibbonWindow 碰到 AvalonDock出现的诡异现象
- php 等额本息+等额本金生成公式
- java程序的结构与类型实验报告_20172301 《Java软件结构与数据结构》实验三报告...
- 波浪能及波能流的推导
- 使用IDEA编写Java程序时遇到的小提醒Common part can be extracted from ‘if‘
- 阿里天池供应链需求预测(二)
- php发送消息给telegram,PHP对接telegram
- 12.静态路由、静态缺省路由