罗列 Python 标准库中的生成器函数 (3)

上一篇 ( 罗列 Python 标准库中的生成器函数 (2) ) 我们列举了 用于合并多个可迭代对象的生成器函数 ,接下来我们继续列举标准库中剩下的生成器函数

有些生成器函数会从一个元素中产出多个值,扩展输入的可迭代对象,如下所示。

4、把输入的各个元素扩展成多个输出元素的生成器函数
模块 函数 说明
itertools combinations(it, out_len) 把 it 产出的 out_len 个元素组合在一起,然后产出
itertools combinations_with_replacement(it,out_len) 把 it 产出的 out_len 个元素组合在一起,然后产出,包含相同元素的组合
itertools count(start=0, step=1) 从 start 开始不断产出数字,按step 指定的步幅增加
itertools cycle(it) 从 it 中产出各个元素,存储各个元素的副本,然后按顺序重复不断地产出各个元素
itertools permutations(it, out_len=None) 把 out_len 个 it 产出的元素排列在一起,然后产出这些排列;out_len的默认值等于 len(list(it))
itertools repeat(item, [times]) 重复不断地产出指定的元素,除非提供 times,指定次数

itertools 模块中的 count 和 repeat 函数返回的生成器“无中生有”:这两个函数都不接受可迭代的对象作为输入。生成器函数第一篇中见过itertools.count 函数。cycle 生成器会备份输入的可迭代对象,然后重复产出对象中的元素。如下演示 count、repeat 和 cycle的用法(count()生成器函数在第一篇已经讲过了,此处按照分类再次演示):

>>> ct = itertools.count() # 1
>>> next(ct) # 2
0
>>> next(ct), next(ct), next(ct) # 3
(1, 2, 3)
>>> list(itertools.islice(itertools.count(1, .3), 3)) # 4
[1, 1.3, 1.6]
>>> cy = itertools.cycle('ABC') # 5
>>> next(cy)
'A'
>>> list(itertools.islice(cy, 7)) # 6
['B', 'C', 'A', 'B', 'C', 'A', 'B']
>>> rp = itertools.repeat(7) # 7
>>> next(rp), next(rp)
(7, 7)
>>> list(itertools.repeat(8, 4)) # 8
[8, 8, 8, 8]
>>> list(map(operator.mul, range(11), itertools.repeat(5))) # 9
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

1、使用 count 函数构建 ct 生成器。
2、获取 ct 中的第一个元素。
3、不能使用 ct 构建列表,因为 ct 是无穷的,所以我获取接下来的 3个元素。
4、如果使用 islice 或 takewhile 函数做了限制,可以从 count 生成器中构建列表。
5、使用 'ABC' 构建一个 cycle 生成器,然后获取第一个元素——'A'。
6、只有受到 islice 函数的限制,才能构建列表;这里获取接下来的 7个元素。
7、构建一个 repeat 生成器,始终产出数字 7。
8、传入 times 参数可以限制 repeat 生成器生成的元素数量:这里会生成 4 次数字 8。
9、repeat 函数的常见用途:为 map 函数提供固定参数,这里提供的是乘数 5。

在 itertools 模块的文档中(https://docs.python.org/3/library/itertools.html), combinations、combinations_with_replacement和 permutations 生成器函数,连同 product 函数,称为组合学生成器(combinatoric generator)。itertools.product 函数和其余的组合学函数有紧密的联系,如以下示例所示:

>>> list(itertools.combinations('ABC', 2)) # 1
[('A', 'B'), ('A', 'C'), ('B', 'C')]
>>> list(itertools.combinations_with_replacement('ABC', 2)) # 2
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
>>> list(itertools.permutations('ABC', 2)) # 3
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')]
>>> list(itertools.product('ABC', repeat=2)) # 4
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'),
('C', 'A'), ('C', 'B'), ('C', 'C')]

1、'ABC' 中每两个元素(len()==2)的各种组合;在生成的元组中,
元素的顺序无关紧要(可以视作集合)。
2、'ABC' 中每两个元素(len()==2)的各种组合,包括相同元素的组
合。
3、'ABC' 中每两个元素(len()==2)的各种排列;在生成的元组中,
元素的顺序有重要意义。
4、'ABC' 和 'ABC'(repeat=2 的效果)的笛卡儿积。

接下来要说的的最后一组生成器函数用于产出输入的可迭代对象中的全部元素,不过会以某种方式重新排列。其中有两个函数会返回多个生成器,分别是 itertools.groupby 和 itertools.tee。这一组里的另一个生成器函数,内置的 reversed 函数,是列举的所述函数中唯一一个不接受可迭代的对象,而只接受序列为参数的函数。这在情理之中,因为reversed 函数从后向前产出元素,而只有序列的长度已知时才能工作。不过,这个函数会按需产出各个元素,因此无需创建反转的副本。另外 itertools.product 函数划分为用于合并的生成器,已经列在了表3、用于合并多个可迭代对象的生成器函数中,因为那一组函数都处理多个可迭代的对象,而下面所列的的生成器最多只能接受一个可迭代的对象

4、用于重新排列元素的生成器函数
模块 函数 说明
itertools groupby(it,key=None) 产出由两个元素组成的元素,形式为 (key,group),其中 key 是分组标准,group 是生成器,用于产出分组里的元素
(内置) reversed(seq) 从后向前,倒序产出 seq 中的元素;seq 必须是序列,或者是实现了 reversed 特殊方法的对象
itertools tee(it, n=2) 产出一个由 n 个生成器组成的元组,每个生成器用于单独产出输入的可迭代对象中的元素

以下先演示 itertools.groupby 函数和内置的 reversed 函数的用法。注意,itertools.groupby 假定输入的可迭代对象要使用分组标准排序;即使不排序,至少也要使用指定的标准分组各个元素。

>>> list(itertools.groupby('LLLLAAGGG')) # 1
[('L', <itertools._grouper object at 0x102227cc0>),
('A', <itertools._grouper object at 0x102227b38>),
('G', <itertools._grouper object at 0x102227b70>)]
>>> for char, group in itertools.groupby('LLLLAAAGG'): # 2
... print(char, '->', list(group))
...
L -> ['L', 'L', 'L', 'L']
A -> ['A', 'A',]
G -> ['G', 'G', 'G']
>>> animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear',
... 'bat', 'dolphin', 'shark', 'lion']
>>> animals.sort(key=len) # 3
>>> animals
['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark',
'giraffe', 'dolphin']
>>> for length, group in itertools.groupby(animals, len): # 4
... print(length, '->', list(group))
...
3 -> ['rat', 'bat']
4 -> ['duck', 'bear', 'lion']
5 -> ['eagle', 'shark']
7 -> ['giraffe', 'dolphin']
>>> for length, group in itertools.groupby(reversed(animals), len): # 5
... print(length, '->', list(group))
...
7 -> ['dolphin', 'giraffe']
5 -> ['shark', 'eagle']
4 -> ['lion', 'bear', 'duck']
3 -> ['bat', 'rat']
>>>

1、groupby 函数产出 (key, group_generator) 这种形式的元组。
2、处理 groupby 函数返回的生成器要嵌套迭代:这里在外层使用 for循环,内层使用列表推导。
3、为了使用 groupby 函数,要排序输入;这里按照单词的长度排序。
4、再次遍历 key 和 group 值对,把 key 显示出来,并把 group 扩展成列表。
5、这里使用 reverse 生成器从右向左迭代 animals。

这一组里的最后一个生成器函数是 iterator.tee,这个函数只有一个作用:从输入的一个可迭代对象中产出多个生成器,每个生成器都可以产出输入的各个元素。产出的生成器可以单独使用,如以下示例所示。

[<itertools._tee object at 0x10222abc8>, <itertools._tee object at 0x10222ac08>]
>>> g1, g2 = itertools.tee('ABC')
>>> next(g1)
'A'
>>> next(g2)
'A'
>>> next(g2)
'B'
>>> list(g1)
['B', 'C']
>>> list(g2)
['C']
>>> list(zip(*itertools.tee('ABC')))
[('A', 'A'), ('B', 'B'), ('C', 'C')]

在三篇介绍生成器函数示例中多次把不同的生成器函数组合在一起使用。其实这就是这些函数的优秀特性:这些函数的参数都是生成器,而返回的结果也是生成器,因此能以很多不同的方式结合在一起使用

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

推荐阅读更多精彩内容