每周一个 Python 模块 | itertools

Python 标准库模块 itertools 提供了很多方便灵活的迭代器工具,熟练的运用可以极大的提高工作效率。

无限迭代器

itertools.count

count(start=0, step=1)

创建一个迭代器,生成从 n 开始的连续整数,如果忽略 n,则从 0 开始计算。示例:

In [2]: for n in itertools.count():
   ...:     if 100000 < n < 100010:
   ...:         print n
   ...:     if n > 1000000:
   ...:         break
   ...:     
100001
100002
100003
100004
100005
100006
100007
100008
100009

itertools.cycle

cycle(iterable)

把传入的一个序列无限重复下去。示例:

In [6]: count = 0

In [7]: for c in itertools.cycle("AB"):
   ...:     if count > 4:
   ...:         break
   ...:     print c
   ...:     count += 1
   ...:     
A
B
A
B
A

itertools.repeat

repeat(object [,times])

创建一个迭代器,重复生成 object,times(如果已提供)指定重复计数,如果未提供 times,将无止尽返回该对象。示例:

In [8]: for x in itertools.repeat("hello world", 5):
   ...:     print x
   ...:     
hello world
hello world
hello world
hello world
hello world

函数式工具

itertools.ifilteritertools.reduceitertools.imapitertools.izip

与内建函数 filter()reduce()map()zip() 有同样的功能,只是返回一个迭代器而不是一个序列。在 Python3 中被去掉,因为默认的内建函数就是返回一个迭代器。

itertools.ifilterfalse

ifilterfalse(function or None, sequence)

python3 为:

filterfalse(function or None, sequence)

与 filter 类似,但仅生成 sequence 中 function(item) 为 False 的项。示例:

In [25]: for elem in itertools.ifilterfalse(lambda x: x > 5, [2, 3, 5, 6, 7]):
   ....:     print elem
   ....:     
2
3
5

itertools.izip_longest

izip_longest(iter1 [,iter2 [...]], [fillvalue=None])

Python3 为:

zip_longest(iter1 [,iter2 [...]], [fillvalue=None])

与 zip 类似,但不同的是它会把最长的 iter 迭代完才结束,其他 iter 如果有缺失值则用 fillvalue 填充。示例:

In [33]: for item in itertools.izip_longest('abcd', '12', fillvalue='-'):
   ....:     print item
   ....:     
('a', '1')
('b', '2')
('c', '-')
('d', '-')

itertools.starmap

starmap(function, sequence)

对序列 sequence 的每个元素作为 function 的参数列表执行,即 function(*item), 返回执行结果的迭代器。只有当 iterable 生成的项适用于这种调用函数的方式时,此函数才有效。示例:

In [35]: seq = [(0, 5), (1, 6), (2, 7), (3, 3), (3, 8), (4, 9)]

In [36]: for item in itertools.starmap(lambda x,y:(x, y, x*y), seq):
    ...:     print "%d * %d = %d" % item
    ...:     
0 * 5 = 0
1 * 6 = 6
2 * 7 = 14
3 * 3 = 9
3 * 8 = 24
4 * 9 = 36

itertools.dropwhile

dropwhile(predicate, iterable)

创建一个迭代器,只要函数 predicate(item) 为 True,就丢弃 iterable 中的项,如果 predicate 返回 False,就会生成 iterable 中的项和所有后续项。即在条件为false之后的第一次, 返回迭代器中剩下来的项。示例:

In [41]: for item in itertools.dropwhile(lambda x: x<1, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
    ...:     print item
    ...:     
1
2
3
4
1
-2

itertools.takewhile

takewhile(predicate, iterable)

与 dropwhile 相反。创建一个迭代器,生成 iterable 中 predicate(item) 为 True 的项,只要 predicate 计算为 False,迭代就会立即停止。示例:

In [28]: for item in itertools.takewhile(lambda x: x < 2, [ -1, 0, 1, 2, 3, 4, 1, -2 ]):
   ....:     print item
   ....:     
-1
0
1

组合工具

itertools.chain

chain(*iterables)

把一组迭代对象串联起来,形成一个更大的迭代器。示例:

In [9]: for c in itertools.chain('ABC', 'XYZ'):
   ...:     print c
   ...:     
A
B
C
X
Y
Z

itertools.product

product(*iterables, repeat=1)

创建一个迭代器,生成多个迭代器集合的笛卡尔积,repeat 参数用于指定重复生成序列的次数。示例:

In [6]: for elem in itertools.product((1, 2), ('a', 'b')):
   ...:     print elem
   ...:     
(1, 'a')
(1, 'b')
(2, 'a')
(2, 'b')

In [7]: for elem in itertools.product((1, 2), ('a', 'b'), repeat=2):
   ...:     print elem
   ...:     
(1, 'a', 1, 'a')
(1, 'a', 1, 'b')
(1, 'a', 2, 'a')
(1, 'a', 2, 'b')
(1, 'b', 1, 'a')
(1, 'b', 1, 'b')
(1, 'b', 2, 'a')
(1, 'b', 2, 'b')
(2, 'a', 1, 'a')
(2, 'a', 1, 'b')
(2, 'a', 2, 'a')
(2, 'a', 2, 'b')
(2, 'b', 1, 'a')
(2, 'b', 1, 'b')
(2, 'b', 2, 'a')
(2, 'b', 2, 'b')

itertools.permutations

permutations(iterable[, r])

返回 iterable 中任意取 r 个元素做排列的元组的迭代器,如果不指定 r,那么序列的长度与 iterable 中的项目数量相同。示例:

In [7]: for elem in itertools.permutations('abc', 2):
   ...:     print elem
   ...:     
('a', 'b')
('a', 'c')
('b', 'a')
('b', 'c')
('c', 'a')
('c', 'b')

In [8]: for elem in itertools.permutations('abc'):
   ...:     print elem
   ...:     
('a', 'b', 'c')
('a', 'c', 'b')
('b', 'a', 'c')
('b', 'c', 'a')
('c', 'a', 'b')
('c', 'b', 'a')

itertools.combinations

combinations(iterable, r)

与 permutations 类似,但组合不分顺序,即如果 iterable 为 "abc",r 为 2 时,ab 和 ba 则视为重复,此时只放回 ab. 示例:

In [10]: for elem in itertools.combinations('abc', 2):
   ....:     print elem
   ....:     
('a', 'b')
('a', 'c')
('b', 'c')

itertools.combinations_with_replacement

combinations_with_replacement(iterable, r)

与 combinations 类似,但允许重复值,即如果 iterable 为 "abc",r 为 2 时,会多出 aa, bb, cc. 示例:

In [14]: for elem in itertools.combinations_with_replacement('abc', 2):
   ....:     print elem
   ....:     
('a', 'a')
('a', 'b')
('a', 'c')
('b', 'b')
('b', 'c')
('c', 'c')

其他工具

itertools.compress

compress(data, selectors)

相当于 bool 选取,只有当 selectors 对应位置的元素为 true 时,才保留 data 中相应位置的元素,否则去除。示例:

In [39]: list(itertools.compress('abcdef', [1, 1, 0, 1, 0, 1]))
Out[39]: ['a', 'b', 'd', 'f']

In [40]: list(itertools.compress('abcdef', [True, False, True]))
Out[40]: ['a', 'c']

itertools.groupby

groupby(iterable[, keyfunc])

对 iterable 中的元素进行分组。keyfunc 是分组函数,用于对 iterable 的连续项进行分组,如果不指定,则默认对 iterable 中的连续相同项进行分组,返回一个 (key, sub-iterator) 的迭代器。示例:

In [45]: for key, value_iter in itertools.groupby('aaabbbaaccd'):
   ....:     print key, list(value_iter)
   ....:     
a ['a', 'a', 'a']
b ['b', 'b', 'b']
a ['a', 'a']
c ['c', 'c']
d ['d']

In [48]: data = ['a', 'bb', 'cc', 'ddd', 'eee', 'f']

In [49]: for key, value_iter in itertools.groupby(data, len):
   ....:     print key, list(value_iter)
   ....:     
1 ['a']
2 ['bb', 'cc']
3 ['ddd', 'eee']
1 ['f']

注意,注意,注意:必须先排序后才能分组,因为 groupby 是通过比较相邻元素来分组的。可以看第二个例子,因为 a 和 f 没有排在一起,所以最后没有分组到同一个列表中。

itertools.islice

islice(iterable, [start,] stop [, step])

切片选择,start 是开始索引,stop 是结束索引,step 是步长,start 和 step 可选。示例:

In [52]: list(itertools.islice([10, 6, 2, 8, 1, 3, 9], 5))
Out[52]: [10, 6, 2, 8, 1]

In [53]: list(itertools.islice(itertools.count(), 6))
Out[53]: [0, 1, 2, 3, 4, 5]

In [54]: list(itertools.islice(itertools.count(), 3, 10))
Out[54]: [3, 4, 5, 6, 7, 8, 9]

In [55]: list(itertools.islice(itertools.count(), 3, 10, 2))
Out[55]: [3, 5, 7, 9]

itertools.tee

tee(iterable, n=2)

从 iterable 创建 n 个独立的迭代器,以元组的形式返回。示例:

In [57]: itertools.tee("abcedf")
Out[57]: (<itertools.tee at 0x7fed7b8f59e0>, <itertools.tee at 0x7fed7b8f56c8>)

In [58]: iter1, iter2 = itertools.tee("abcedf")

In [59]: list(iter1)
Out[59]: ['a', 'b', 'c', 'e', 'd', 'f']

In [60]: list(iter2)
Out[60]: ['a', 'b', 'c', 'e', 'd', 'f']

In [61]: itertools.tee("abcedf", 3)
Out[61]:
(<itertools.tee at 0x7fed7b8f5cf8>,
 <itertools.tee at 0x7fed7b8f5cb0>,
 <itertools.tee at 0x7fed7b8f5b00>)




相关文档:

http://blog.konghy.cn/2017/04/25/python-itertools/

https://juejin.im/post/5af56230f265da0b93485cca#heading-15

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • PYTHON-进阶-ITERTOOLS模块小结转自wklken:http://wklken.me/posts/20...
    C_Y_阅读 953评论 0 2
  • 本文翻译自Functional Programming Howto 本文将介绍Python中函数式编程的特性。在对...
    大蟒传奇阅读 2,598评论 4 14
  • 青青草,羞羞花, 暖风鹅黄枝头桠, 一缕春光嫩叶碧, 响午儿郎正回家; 萌萌事,悄悄话, 纸条儿粉笔黑板擦, 羊肠...
    一言一语一行阅读 292评论 0 2
  • (调姿)选择任意舒适的坐姿坐在瑜伽垫上,双手向后拨动臀肌让坐骨坐实地面,收腹,腰背挺直,双肩后展下沉,头颈端正 (...
    牛奶瓶子啦阅读 720评论 0 0
  • 刚刚看了《28岁未成年》霍建华闫妮主演。夏凉吃完广告上的巧克力一下子回到28岁,那个有自我,的少女心里。28岁多么...
    丽小美阅读 340评论 0 0