python 标准库中的生成器函数

1. 用于过滤的生成器函数

模块函数

说明

itertoolscompress(it,selector_it)并行处理两个可迭代的对象;如果 selector_it 中的元素是真值,产出 it 中对应的元素
itertoolsdropwhile(predicate, it)处理 it,跳过 predicate 的计算结果为真值的元素,然后产出剩下的各个元素(不再进一步检查)
(内置)filter(predicate, it)把 it 中的各个元素传给 predicate,如果 predicate(item) 返回真值,那么产出对应的元素;如果 predicate 是 None,那么只产出真值元素
itertoolsfilterfalse(predicate, it)与 filter 函数的作用类似,不过 predicate 的逻辑是相反的:predicate 返回假值时产出对应的元素
itertoolsislice(it, stop) 或
islice(it, start,stop,step=1)
产出 it 的切片,作用类似于 s[:stop] 或 s[start:stop:step],不过it 可以是任何可迭代的对象,而且这个函数实现的是惰性操作
itertoolstakewhile(predicate, it)predicate 返回真值时产出对应的元素,然后立即停止,不再继续检查

演示用于过滤的生成器函数:

def vowel(c):
    return c.lower() in 'aeiou'

print(list(filter(vowel, 'Aardvark'))) # ➊

import itertools
print(list(itertools.filterfalse(vowel, 'Aardvark'))) # ➋

print(list(itertools.dropwhile(vowel, 'Aardvark'))) # ➌

print(list(itertools.takewhile(vowel, 'Aardvark'))) # ➍

print(list(itertools.compress('Aardvark', (1,0,1,1,0,1)))) # ➎

print(list(itertools.islice('Aardvark', 4))) # ➏

print(list(itertools.islice('Aardvark', 4, 7))) # ➐

print(list(itertools.islice('Aardvark', 1, 7, 2))) # ➑

['A', 'a', 'a'] # ➊
['r', 'd', 'v', 'r', 'k'] # ➋
['r', 'd', 'v', 'a', 'r', 'k'] # ➌
['A', 'a']  # ➍
['A', 'r', 'd', 'a'] # ➎
['A', 'a', 'r', 'd'] # ➏
['v', 'a', 'r'] # ➐
['a', 'd', 'a'] # ➑

2. 用于映射的生成器函数

模块函数说明
itertoolsaccumulate(it, [func])产出累积的总和;如果提供了 func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果
(内置)enumerate(iterable,start=0)产出由两个元素组成的元组,结构是 (index, item),其中 index 从 start 开始计数,item 则从 iterable 中获取
(内置)map(func, it1, [it2, ..., itN])把 it 中的各个元素传给func,产出结果;如果传入 N 个可迭代的对象,那么 func 必须能接受 N 个参数,而且要并行处理各个可迭代的对象
itertoolsstarmap(func, it)把 it 中的各个元素传给 func,产出结果;输入的可迭代对象应该产出可迭代的元素 iit,然后以 func(*iit) 这种形式调用 func

1) 演示 itertools.accumulate 生成器函数:

sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
import itertools

print(list(itertools.accumulate(sample))) # ➊  计算总和

print(list(itertools.accumulate(sample, min))) # ➋ 计算最小值

print(list(itertools.accumulate(sample, max))) # ➌ 计算最大值

import operator
print(list(itertools.accumulate(sample, operator.mul))) # ➍ 计算乘积

print(list(itertools.accumulate(range(1, 11), operator.mul))) # ➎ 从 1! 到 10!,计算各个数的阶乘

[5, 9, 11, 19, 26, 32, 35, 35, 44, 45]  # ➊
[5, 4, 2, 2, 2, 2, 2, 0, 0, 0] # ➋
[5, 5, 5, 8, 8, 8, 8, 8, 9, 9] # ➌
[5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0] # ➍
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800] # ➎

2) 演示用于映射的生成器函数:

print(list(enumerate('albatroz', 1))) # ➊ 从 1 开始,为单词中的字母编号

import operator
print(list(map(operator.mul, range(11), range(11)))) # ❷ 从 0 到 10,计算各个整数的平方。

# ❸ 计算两个可迭代对象中对应位置上的两个元素之积,元素最少的那个可迭代对象到头后就停止。

print(list(map(operator.mul, range(11), [2, 4, 8])))

print(list(map(lambda a, b: (a, b), range(11), [2, 4, 8]))) # ➍ 作用等同于内置的 zip 函数

import itertools

# ➎ 从 1 开始,根据字母所在的位置,把字母重复相应的次数
print(list(itertools.starmap(operator.mul, enumerate('albatroz', 1))))

sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
print(list(itertools.starmap(lambda a, b: b/a, (enumerate(itertools.accumulate(sample), 1))))) # ➏ 计算平均值。

[(1, 'a'), (2, 'l'), (3, 'b'), (4, 'a'), (5, 't'), (6, 'r'), (7, 'o'), (8, 'z')] # ➊
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100] # ❷
[0, 4, 16] # ❸
[(0, 2), (1, 4), (2, 8)] # ➍
['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz'] # ➎
[5.0, 4.5, 3.6666666666666665, 4.75, 5.2, 5.333333333333333, 5.0, 4.375, 4.888888888888889, 4.5]  # ➏

3. 合并多个可迭代对象的生成器函数

模块函数说明
itertoolschain(it1, ..., itN)先产出 it1 中的所有元素,然后产出 it2 中的所有元素,以此类推,无缝连接在一起
itertoolschain.from_iterable(it)产出 it 生成的各个可迭代对象中的元素,一个接一个,无缝连接在一起;it 应该产出可迭代的元素,例如可迭代的对象列表
itertoolsproduct(it1, ..., itN,
repeat=1)
计算笛卡儿积:从输入的各个可迭代对象中获取元素,合并成由 N个元素组成的元组,与嵌套的 for 循环效果一样;repeat 指明重复处理多少次输入的可迭代对象
(内置)zip(it1, ..., itN)并行从输入的各个可迭代对象中获取元素,产出由 N 个元素组成的元组,只要有一个可迭代的对象到头了,就默默地停止
itertoolszip_longest(it1, ...,
itN, fillvalue=None)
并行从输入的各个可迭代对象中获取元素,产出由 N 个元素组成的元组,等到最长的可迭代对象到头后才停止,空缺的值使用fillvalue 填充

1) 演示用于合并的生成器函数:

import itertools

print(list(itertools.chain('ABC', range(2)))) # ➊ 调用 chain 函数时通常传入两个或更多个可迭代对象。

print(list(itertools.chain(enumerate('ABC')))) # ❷ 如果只传入一个可迭代的对象,那么 chain 函数没什么用。

'''❸ 但是 chain.from_iterable 函数从可迭代的对象中获取每个元素,然后按顺序把元素连接起来,前提是各个元素本身也是# 可迭代的对象。'''
print(list(itertools.chain.from_iterable(enumerate('ABC'))))

print(list(zip('ABC', range(5)))) # ❹ zip 常用于把两个可迭代的对象合并成一系列由两个元素组成的元组。

#❺ zip 可以并行处理任意数量个可迭代的对象,不过只要有一个可迭代的对象到头了,生成器就停止
print(list(zip('ABC', range(5), [10, 20, 30, 40])))

#❻ itertools.zip_longest 函数的作用与 zip 类似,不过输入的所有可迭代对象都会处理到头,如果需要会填充 None。
print(list(itertools.zip_longest('ABC', range(5))))

print(list(itertools.zip_longest('ABC', range(5), fillvalue='?'))) # ➐ fillvalue 关键字参数用于指定填充的值。

['A', 'B', 'C', 0, 1] # ➊
[(0, 'A'), (1, 'B'), (2, 'C')] # ➋
[0, 'A', 1, 'B', 2, 'C'] # ➌
[('A', 0), ('B', 1), ('C', 2)] # ➍
[('A', 0, 10), ('B', 1, 20), ('C', 2, 30)]  # ➎
[('A', 0), ('B', 1), ('C', 2), (None, 3), (None, 4)]  # ➏
[('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)] # ➐

2) 演示 itertools.product 生成器函数:

import itertools

#➊ 三个字符的字符串与两个整数的值域得到的笛卡儿积是六个元组 (因为 3 * 2 等于6)
print(list(itertools.product('ABC', range(2))))

#➋ 两张牌('AK')与四种花色得到的笛卡儿积是八个元组。
suits = 'spades hearts diamonds clubs'.split()
print(list(itertools.product('AK', suits)))

#➌ 如果传入一个可迭代的对象,product 函数产出的是一系列只有一个元素的元组,不是特别有用。
print(list(itertools.product('ABC')))

#➍ repeat=N 关键字参数告诉 product 函数重复 N 次处理输入的各个可迭代对象。
print(list(itertools.product('ABC', repeat=2)))

print(list(itertools.product(range(2), repeat=3)))

rows = itertools.product('AB', range(2), repeat=2)
for row in rows: print(row)

[('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)] #➊
[('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs')] #➋
[('A',), ('B',), ('C',)] #➌
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')] #➍
[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
('A', 0, 'A', 0)
('A', 0, 'A', 1)
('A', 0, 'B', 0)
('A', 0, 'B', 1)
('A', 1, 'A', 0)
('A', 1, 'A', 1)
('A', 1, 'B', 0)
('A', 1, 'B', 1)
('B', 0, 'A', 0)
('B', 0, 'A', 1)
('B', 0, 'B', 0)
('B', 0, 'B', 1)
('B', 1, 'A', 0)
('B', 1, 'A', 1)
('B', 1, 'B', 0)
('B', 1, 'B', 1)

4.把输入的各个元素扩展成多个输出元素的生成器函数

模块函数说明
itertoolscombinations(it, out_len)把 it 产出的 out_len 个元素组合在一起,然后产出
itertoolscombinations_with_replacement(it, out_len)把 it 产出的 out_len 个元素组合在一起,然后产出,包含相同元素的组合
itertoolscount(start=0, step=1)从 start 开始不断产出数字,按 step 指定的步幅增加
itertoolscycle(it)从 it 中产出各个元素,存储各个元素的副本,然后按顺序重复不断地产出各个元素
itertoolspermutations(it, out_len=None)把 out_len 个 it 产出的元素排列在一起,然后产出这些排列;out_len 的默认值等于 len(list(it))
itertoolsrepeat(item, [times]) 重复不断地产出指定的元素,除非提供 times,指定次数

1) 演示 count、repeat 和 cycle 的用法:

import itertools, operator

#➊ 使用 count 函数构建 ct 生成器。
ct = itertools.count()
#➋ 获取 ct 中的第一个元素。
print(next(ct))
#➌ 不能使用 ct 构建列表,因为 ct 是无穷的,所以我获取接下来的 3 个元素。
print(next(ct), next(ct), next(ct))
#➍ 如果使用 islice 或 takewhile 函数做了限制,可以从 count 生成器中构建列表。
print(list(itertools.islice(itertools.count(1, .3), 3)))

#➎ 使用 'ABC' 构建一个 cycle 生成器,然后获取第一个元素——'A'。
cy = itertools.cycle('ABC') # ➎
print(next(cy))
#➏ 只有受到 islice 函数的限制,才能构建列表;这里获取接下来的 7 个元素。
print(list(itertools.islice(cy, 7)))

#➐ 构建一个 repeat 生成器,始终产出数字 7。
rp = itertools.repeat(7)
print(next(rp), next(rp))
#➑传入 times 参数可以限制 repeat 生成器生成的元素数量:这里会生成 4 次数字 8
print(list(itertools.repeat(8, 4)))
#❾ repeat 函数的常见用途:为 map 函数提供固定参数,这里提供的是乘数 5。
print(list(map(operator.mul, range(11), itertools.repeat(5))))

0  #➋
1 2 3 #➌
[1, 1.3, 1.6] #➍
A
['B', 'C', 'A', 'B', 'C', 'A', 'B'] #➏
7 7
[8, 8, 8, 8] #➑
[0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50] #❾

2) 组合学生成器函数会从输入的各个元素中产出多个值:

import itertools

#➊ 'ABC' 中每两个元素(len()==2)的各种组合;在生成的元组中,元素的顺序无关紧要(可以视作集合)。
print(list(itertools.combinations('ABC', 2)))

#➋ 'ABC' 中每两个元素(len()==2)的各种组合,包括相同元素的组合。
print(list(itertools.combinations_with_replacement('ABC', 2)))

#➌  'ABC' 中每两个元素(len()==2)的各种排列;在生成的元组中,元素的顺序有重要意义。
print(list(itertools.permutations('ABC', 2)))

#➍ 'ABC' 和 'ABC'(repeat=2 的效果)的笛卡儿积。
print(list(itertools.product('ABC', repeat=2)))

[('A', 'B'), ('A', 'C'), ('B', 'C')] #➊
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')] #➋ 
[('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'C'), ('C', 'A'), ('C', 'B')] #➌ 
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')] #➍

5. 用于重新排列元素的生成器函数

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

1) itertools.groupby 函数的用法 

import itertools

#➊ groupby 函数产出 (key, group_generator) 这种形式的元组。
print(list(itertools.groupby('LLLLAAGGG')))
#➋ 处理 groupby 函数返回的生成器要嵌套迭代:这里在外层使用 for 循环,内层使用列表推导。
for char, group in itertools.groupby('LLLLAAAGG'):
    print(char, '->', list(group))

animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear','bat', 'dolphin', 'shark', 'lion']
#➌ 为了使用 groupby 函数,要排序输入;这里按照单词的长度排序。
animals.sort(key=len)
print(animals)
#➍ 再次遍历 key 和 group 值对,把 key 显示出来,并把 group 扩展成列表。
for length, group in itertools.groupby(animals, len):
    print(length, '->', list(group))

#➎ 这里使用 reverse 生成器从右向左迭代 animals。
for length, group in itertools.groupby(reversed(animals), len):
    print(length, '->', list(group))

[('L', <itertools._grouper object at 0x2b1bbd84f358>), ('A', <itertools._grouper object at 0x2b1bbd84f390>), ('G', <itertools._grouper object at 0x2b1bbd84f3c8>)] #➊

L -> ['L', 'L', 'L', 'L'] #➋
A -> ['A', 'A', 'A']
G -> ['G', 'G']

['rat', 'bat', 'duck', 'bear', 'lion', 'eagle', 'shark', 'giraffe', 'dolphin'] #➌

3 -> ['rat', 'bat'] #➍
4 -> ['duck', 'bear', 'lion']
5 -> ['eagle', 'shark']
7 -> ['giraffe', 'dolphin']

7 -> ['dolphin', 'giraffe'] #➎
5 -> ['shark', 'eagle']
4 -> ['lion', 'bear', 'duck']
3 -> ['bat', 'rat']

2) itertools.tee函数产出多个生成器,每个生成器都可以产出输入的各个元素 

import itertools

print(list(itertools.tee('ABC')))

g1, g2 = itertools.tee('ABC')
print(next(g1))
print(next(g2))
print(next(g2))
print(list(g1))
print(list(g2))
print(list(zip(*itertools.tee('ABC'))))

[<itertools._tee object at 0x2b7d54aac148>, <itertools._tee object at 0x2b7d54aac188>]

A
A
B
['B', 'C']
['C']
[('A', 'A'), ('B', 'B'), ('C', 'C')] 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值