设为首页 收藏本站
查看: 1199|回复: 0

[经验分享] python 高效的 itertools 模块

[复制链接]

尚未签到

发表于 2018-8-15 06:16:07 | 显示全部楼层 |阅读模式
  迭代器的特点是:惰性求值(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,否则为无限
  下面,让我们看看一些例子。
  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
  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
  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 模块提供了多个函数(类),接收一个或多个迭代对象作为参数,对它们进行组合、分组和过滤等:

  •   chain()
  •   compress()
  •   dropwhile()
  •   groupby()
  •   ifilter()
  •   ifilterfalse()
  •   islice()
  •   imap()
  •   starmap()
  •   tee()
  •   takewhile()
  •   izip()
  •   izip_longest()
  chain
  chain 的使用形式如下:
chain(iterable1, iterable2, iterable3, ...)
  chain 接收多个可迭代对象作为参数,将它们『连接』起来,作为一个新的迭代器返回。
>>> from itertools import chain  
>>>
  
>>> for item in chain([1, 2, 3], ['a', 'b', 'c']):
  
...     print item
  
...
  
1
  
2
  
3
  
a
  
b
  
c
  chain 还有一个常见的用法:
chain.from_iterable(iterable)
  接收一个可迭代对象作为参数,返回一个迭代器:
>>> from itertools import chain  
>>>
  
>>> string = chain.from_iterable('ABCD')
  
>>> string.next()
  
'A'
  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']
  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, 2, 1]
  
>>>
  
>>> list(dropwhile(lambda x: x > 3, [2, 1, 6, 5, 4]))
  
[2, 1, 6, 5, 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']
  ifilter
  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
  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]
  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]
  imap
  imap 类似 map 操作,它的使用形式如下:
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]
  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>)
  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]))
  
[]
  izip
  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_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 模块还提供了多个组合生成器函数,用于求序列的排列、组合等:

  •   product
  •   permutations
  •   combinations
  •   combinations_with_replacement
  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')]
  
>>>
  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')]
  
>>>
  combinations
  combinations 用于求序列的组合,它的使用形式如下:
combinations(iterable, r)
  其中,r 指定生成组合的元素的长度。
>>> from itertools import combinations  
>>>
  
>>> list(combinations('ABC', 2))
  
[('A', 'B'), ('A', 'C'), ('B', 'C')]
  combinations_with_replacement
  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')]
  小结

  •   itertools 模块提供了很多用于产生多种类型迭代器的函数,它们的返回值不是 list,而是迭代器。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-551852-1-1.html 上篇帖子: python 简单小爬虫 下篇帖子: Python之字符串格式化
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表