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_longestizip类似,但迭代过程会持续到所有可迭代对象的元素都被迭代完。它的形式如下:


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_replacementcombinations类似,但它生成的组合包含自身元素。

>>> 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 模块相关推荐

  1. python itertools模块位置_Python高效编程之itertools模块详解

    0 前言 说到处理循环,我们习惯使用for, while等,比如依次打印每个列表中的字符:lis = [ I , love , python ] for i in lis: print(i) I lo ...

  2. python itertools模块chain函数功能详解 itertools.chain(*iterable)

    Itertools模块, itertools提供了高效快捷的用于操作迭代对象的函数.通过使用这个模块,可以简化代码. Itertools.chain语法 Itertools.chain(*iterab ...

  3. Python 的 itertools 模块

    Python 当中的 itertools 模块在程序员中的存在感一直不高,可能是大家真正用到的时候并不多.然而,最近它却成功引起了我的注意,它在 Python 求列表的所有 k 阶子列 时大放异彩,所 ...

  4. itertools模块

    Python-进阶-itertools模块小结 Python-进阶-itertools模块小结 组成 第一部分 itertools.count(start=0, step=1) itertools.c ...

  5. python itertools模块详解

    目录 简介 无穷迭代器 count() cycle() repeat() 有限迭代器 chain() groupby() accumulate() 组合迭代器 product() permutatio ...

  6. Pyhton 内置 itertools 模块chain、accumulate、compress、drop、take等函数使用

    Python 内置的 itertools 模块使用了 yield 生成器. 1. chain 拼接迭代器 chain 函数实现元素拼接,原型如下,参数 * 表示可变的参数: chain(*iterab ...

  7. python自带intertool模块找不到_Python itertools模块:生成迭代器(示例分析)

    1 itertools 模块中主要包含了一些用于生成迭代器的函数.在 Python 的交互式解释器中先导入 itertools 模块,然后输入 e for e in dir(itertools) if ...

  8. python自带intertool模块找不到_介绍Python中内置的itertools模块

    Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数. 首先,我们看看itertools提供的几个"无限"迭代器: >>> import ...

  9. Python itertools模块

    今天学了简单好玩的模块.itertools模块,简单的说,itertools模块就是产生一个循环器 来看下这个模块的功能都有哪些吧 无穷循环器 count()  从開始的数字一直数下去 count(1 ...

最新文章

  1. 如果不是为了面试,AI工程师刷题有用吗?
  2. JAVA一个项目的路径为_java 得到项目路径
  3. 记录一下halcon例程报错和两个视觉库感兴趣区域绘制
  4. 用真实脑电波提高魔法伤害!硬核玩家改造《上古卷轴V》,脑机接口控制魔法施放...
  5. 百度2011大会见闻:百度开始推出耀主页
  6. python测试用例管理模块_python-selenium并发执行测试用例(方法一 各模块每一条并发执行)...
  7. WebP 在减少图片体积和流量上的效果如何?—— WebP 技术实践分享
  8. Asp.net MVC在Razor中输出Html的两种方式
  9. [转载] Java中的final变量、final方法和final类
  10. c++ string类_C++|细说STL string类概貌及底层细节
  11. Linux CTF 逆向入门
  12. LaTex使用的一些技巧记录
  13. Microsoft.Windows.Controls.Ribbon.RibbonWindow 碰到 AvalonDock出现的诡异现象
  14. php 等额本息+等额本金生成公式
  15. java程序的结构与类型实验报告_20172301 《Java软件结构与数据结构》实验三报告...
  16. 波浪能及波能流的推导
  17. 使用IDEA编写Java程序时遇到的小提醒Common part can be extracted from ‘if‘
  18. 阿里天池供应链需求预测(二)
  19. php发送消息给telegram,PHP对接telegram
  20. 12.静态路由、静态缺省路由

热门文章

  1. 我推荐阅读的微信公众号-人文类
  2. 如何使用Hbuilderx运行微信小程序
  3. overflow:hidden的使用
  4. HTML5开发工具介绍-HBuilder
  5. linux关闭终端而不关闭通过该终端打开的软件
  6. 中国5G、新能源汽车领先全球,将引领第四次工业革命
  7. Android 无障碍服务设置
  8. 笔记本通过网线共享网络
  9. 华为堡垒机_堡垒机是干什么的?
  10. 华为云软件开发云VS开发痛点=?