第14章:扩展-标准库中的生成器函数

标准库提供了很多生成器,有用于逐行迭代纯文本文件的对象,还有出色的 os.walk 函数。 这个函数在遍历目录树的过程中产出文件名,因此递归搜索文件系统像 for 循环那样简单。

os.walk 生成器函数的作用令人赞叹,不过本节专注于通用的函数:参数为任意的可迭代对象,返回值是生成器,用于生成选中的、计算出的 和重新排列的元素。

表14-1 用于过滤的生成器函数:从输入的可迭代对象中产出元素的子集,而且不修改元素本身。

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

  6. takewhile(predicate, it):predicate 返回真值时产出对应的元素,然后立即停止,不再继续检查;

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


# filter(predicate, it) ==============================================
print(list(filter(vowel, 'Aardvark')))  # ['A', 'a', 'a']

# filterfalse(predicate, it) =========================================
print(list(filterfalse(vowel, 'Aardvark')))  # ['r', 'd', 'v', 'r', 'k']

# compress(it, selector_it) ==========================================
print(list(compress('Aardvark', (1, 0, 1, 1, 0, 1))))  # ['A', 'r', 'd', 'a']

# islice(it, start, stop, step=1) ====================================
print(list(islice('Aardvark', 4)))  # ['A', 'a', 'r', 'd']
print(list(islice('Aardvark', 4, 7)))  # ['v', 'a', 'r']
print(list(islice('Aardvark', 1, 7, 2)))  # ['a', 'd', 'a']

# dropwhile(predicate, it) ===========================================
print(list(dropwhile(vowel, 'Aardvark')))  # ['r', 'd', 'v', 'a', 'r', 'k']

# takewhile(predicate, it) ===========================================
print(list(takewhile(vowel, 'Aardvark')))  # ['A', 'a']

 

表14-2 用于映射的生成器函数:在输入的单个可迭代对象中的各个元素上做计算,然后返回结果。
         (这里所说的“映射”与字典没有关系,而与内置的 map 函数有关)

  1. map(func, it1, [it2, ...]):把 it 中的各个元素传给 func,产出结果;如果传入 N 个可迭代的对象,那么 func 必须能接受 N 个参数,而且要并行处理各个可迭代的对象;

  2. starmap(func, it):将 it 中的元素,以元组拆包的形式传递给 func,产出结果;

  3. enumerate(iterable, start=0):产出由两个元素组成的元组,结构是 :(index, item),其中 index 从 start 开始计数,item 则从 iterable 中获取;

  4. accumulate(it, [func]):产出累积的总和;如果提供了 func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果;

import operator
from itertools import *

# map(func, it1, [it2, ...]) =======================================
m = [1, 2, 3]
n = ['a', 'b', 'c']
o = ['x', 'y', 'z']


def func(i, j, k):
    return i, j, k


print(list(map(func, m, n, o)))  # [(1, 'a', 'x'), (2, 'b', 'y'), (3, 'c', 'z')]

# enumerate(iterable, start=0) =====================================
x = ['a', 'b', 'c']
print(list(enumerate(x)))  # [(0, 'a'), (1, 'b'), (2, 'c')]
print(list(enumerate(x, start=1)))  # [(1, 'a'), (2, 'b'), (3, 'c')]

# accumulate(it, [func]) ===========================================
sample = [5, 4, 2, 8, 7, 6, 3, 0, 9, 1]
# 求和
list(accumulate(sample))  # [5, 9, 11, 19, 26, 32, 35, 35, 44, 45]
# 取最小值
list(accumulate(sample, min))  # [5, 4, 2, 2, 2, 2, 2, 0, 0, 0]
# 阶乘
list(accumulate(range(1, 11), operator.mul))  # [1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800]


# starmap(func, it) ================================================
def func(*it):
    return it


y = ['a1', 'b2', 'c3']
print(list(starmap(func, x)))  # [('a', '1'), ('b', '2'), ('c', '3')]

 

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

  1. zip(it1, ..., itN):并行从输入的 N 个可迭代对象中获取元素,产出由 N 个元素组成的元组,只要有一个可迭代对象到头了,就默默地停止;

  2. zip_longest(it1, ..., itN, fillvalue=None):并行从输入的 N 个可迭代对象中获取元素,产出由 N 个元素组成的元组,等到最长的可迭代对象到头后才停止,空缺的值使用 fillvalue 填充;

  3. chain(it1, ..., itN):先产出 it1 中的所有元素,然后产出 it2 中的所有元素,以此类推,无缝连接在一起;

  4. chain.from_iterable(it):产出 it 生成的各个可迭代对象中的元素,一个接一个,无缝连接在一起;it 应该产出可迭代的元素,例如可迭代的对象列表;

  5. product(it1, ..., itN, repeat=1):计算笛卡儿积:从输入的各个可迭代对象中获 取元素,合并成由 N 个元素组成的元组,与嵌套的 for 循环效果一样;repeat 指明重复处理多少次输入的可迭代对象;

from itertools import *

# zip(it1, ..., itN) ==============================================
print(list(zip('ABC', range(5))))  # [('A', 0), ('B', 1), ('C', 2)]
print(list(zip('ABC', range(5), [10, 20, 30, 40])))  # [('A', 0, 10), ('B', 1, 20), ('C', 2, 30)]

# zip_longest(it1, ..., itN, fillvalue=None) ======================
print(list(zip_longest('ABC', range(5))))  # [('A', 0), ('B', 1), ('C', 2), (None, 3), (None, 4)]
print(list(zip_longest('ABC', range(5), fillvalue='?')))  # [('A', 0), ('B', 1), ('C', 2), ('?', 3), ('?', 4)]

# chain(it1, ..., itN) ============================================
print(list(chain('ABC', range(2))))  # ['A', 'B', 'C', 0, 1]
print(list(chain(enumerate('ABC'))))  # [(0, 'A'), (1, 'B'), (2, 'C')]

# chain.from_iterable(it) =========================================
print(list(chain.from_iterable(enumerate('ABC'))))  # [0, 'A', 1, 'B', 2, 'C']

# product(it1, ..., itN, repeat=1) ================================
list(product('ABC', range(2)))  # [('A', 0), ('A', 1), ('B', 0), ('B', 1), ('C', 0), ('C', 1)]
list(product('ABC', repeat=2))  
# [('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'A'), ('B', 'B'), ('B', 'C'), ('C', 'A'), ('C', 'B'), ('C', 'C')]

rows = product('AB', range(2), repeat=2)
for row in rows:
    print(row)
# ('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)

 

表14-4 用于重新排列元素的生成器函数​​​​​​​

  1. reversed(seq):从后向前,倒序产出 seq 中的元素;seq 必须是序列,或者是实现了 __reversed__ 特殊方法的对象;

  2. groupby(it,key=None):产出由两个元素组成的元素,形式为 (key, group),其中 key 是分组标准,group 是生成器, 用于产出分组里的元素;

from itertools import *

# reversed(seq) =================================================
x = ['a', 'c', 'd', 1, 'g', 'z']
c = reversed(x)
print(list(c))  # ['z', 'g', 1, 'd', 'c', 'a']


# groupby(it,key=None)  =========================================
print(list(groupby('LLLLAAGGG')))
# [('L', <itertools._grouper object at 0x1100a04a8>),
# ('A', <itertools._grouper object at 0x1100f2390>),
# ('G', <itertools._grouper object at 0x1100f2400>)]

for char, group in groupby('LLLLAAAGG'):
    print(char, '->', list(group))
# L -> ['L', 'L', 'L', 'L']
# A -> ['A', 'A', 'A']
# G -> ['G', 'G']


animals = ['duck', 'eagle', 'rat', 'giraffe', 'bear', 'bat', 'dolphin', 'shark', 'lion']

for length, group in groupby(animals, len):
    print(length, '->', list(group))
# 4 -> ['duck']
# 5 -> ['eagle']
# 3 -> ['rat']
# 7 -> ['giraffe']
# 4 -> ['bear']
# 3 -> ['bat']
# 7 -> ['dolphin']
# 5 -> ['shark']
# 4 -> ['lion']

animals.sort(key=len)
for length, group in groupby(animals, len):
    print(length, '->', list(group))
# 3 -> ['rat', 'bat']
# 4 -> ['duck', 'bear', 'lion']
# 5 -> ['eagle', 'shark']
# 7 -> ['giraffe', 'dolphin']

 

表 14-5 可迭代的归约函数:接受一个可迭代的对象,然后返回单个结果的函数叫“归约”函数。

  1. all(it):it 中的所有元素都为真值时返回 True,否则返回 False,all([]) 返回 True;

  2. any(it):只要 it 中有元素为真值就返回 True,否则返回 False,any([]) 返回 False;

  3. max(it, [key=,] [default=]):返回 it 中值最大的元素;key 是排序函数,与 sorted 函数中的一样;如果可迭代的对象为空,返回 default;

  4. min(it, [key=,] [default=]):返回 it 中值最小的元素;key 是排序函数,与 sorted 函数中的一样;如果可迭代的对象为空,返回 default;

  5. reduce(func, it, [initial]):把 it 的前两个元素传给 func,然后把计算结果和第三个元素传给 func,以此类推,返回最后的结果;如果提供了 initial,把它当作第一个元素传入;

  6. sum(it, start=0):it 中所有元素的总和,如果提供可选的 start,会把它加上(计算浮点数的加法时,可以使用 math.fsum 函数提高精度);

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值