python生成器函数_罗列 Python 标准库中的生成器函数 (1)

实际编码中,我们可能会碰到这样的需求,实现一个生成器函数,但是实现之前要知道标准库中有什么可用, 否则很可能会重新发明轮子,举个栗子~

实现一个无穷等差数列,首项 start = 0, 公差 step = 2, 很显然你不能用列表的形式实现,不然肯定会内存溢出,你可以直接写一个生成器,但是,为什么不用内置的呢

import itertools

gen = itertools.count(start, step) # 此时 gen 是一个生成器

for _ in range(100): # 比如我们想打印前 100 个的值

print(next(gen))

Python 3 中的 itertools 模块提供了多个生成器函数, 结合使用能实现很多用法。

上面所使用的 itertools.count 函数返回的生成器能生成多个数。 如果不传

入参数, itertools.count 函数会生成从零开始的整数数列。 不过,

我们可以提供可选的 start 和 step 值;

说到多个生成器结合使用,我们对上面的例子加个条件,生成的等差数列的最大值不超过 100,很显然 itertools.count 无法做到,此时我们可以用到 itertools 下面的另一个生成器函数 itertools.takewhile()

import itertools

gen = itertools.takewhile(lambda n: n < 100, itertools.count(0, 2))

for value in gen:

print(value)

itertools.takewhile 函数会生成一个使用另一个生成器的生成器, 在指定的条件计算结果为 False 时停止

事实上 Python 标准库提供了很多生成器, 有用于逐行迭代纯文本文件的对象, 还有出色的 os.walk 函数。这个函数在遍历目录树的过程中产出文件名, 因此递归搜索文件系统像for 循环那样简单。另外有些在 itertools 和 functools 模块中,下面按类别列举吧

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

模块

函数

说明

itertools

compress(it,selector_it)

并行处理两个可迭代的对象; 如果 selector_it中的元素是真值, 产出 it 中对应的元素

itertools

dropwhile(predicate,it)

处理 it, 跳过 predicate 的计算结果为真值的元素, 然后产出剩下的各个元素(不再进一步检查)

(内置)

filter(predicate, it)

把 it 中的各个元素传给 predicate,如果predicate(item) 返回真值, 那么产出对应的元素; 如果 predicate 是None, 那么只产出真值元素

itertools

filterfalse(predicate,it)

与 filter 函数的作用类似, 不过 predicate 的逻辑是相反的: predicate 返回假值时产出对应的元素

itertools

islice(it, stop) 或islice(it, start,stop, step=1)

产出 it 的切片, 作用类似于 s[:stop] 或s[start:stop:step], 不过 it 可以是任何可迭代的对象, 而且这个函数实现的是惰性操作

itertools

takewhile(predicate,it)

predicate 返回真值时产出对应的元素, 然后立即停止, 不再继续检查

下面在控制台演示各个函数的用法

>>> def vowel(c):

... return c.lower() in 'aeiou'

...

>>> list(filter(vowel, 'Aardvark'))

['A', 'a', 'a']

>>> import itertools

>>> list(itertools.filterfalse(vowel, 'Aardvark'))

['r', 'd', 'v', 'r', 'k']

>>> list(itertools.dropwhile(vowel, 'Aardvark'))

['r', 'd', 'v', 'a', 'r', 'k']

>>> list(itertools.takewhile(vowel, 'Aardvark'))

['A', 'a']

>>> list(itertools.compress('Aardvark', (1,0,1,1,0,1)))

['A', 'r', 'd', 'a']

>>> list(itertools.islice('Aardvark', 4))

['A', 'a', 'r', 'd']

>>> list(itertools.islice('Aardvark', 4, 7))

['v', 'a', 'r']

>>> list(itertools.islice('Aardvark', 1, 7, 2))

['a', 'd', 'a']

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

模块

函数

说明

itertools

accumulate(it, [func])

产出累计的总和;如果提供了 func,那么把前两个元素传给它,然后把计算结果和下一个元素传给它,以此类推,最后产出结果

(内置)

enumerate(iterable, start=0)

产出由两个元素组成的元祖,结构是 (index, item),其中index 从 start 开始计数,item 则从 iterable 中获取

(内置)

map(func, it1, [it2, ..., itN])

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

itertools

starmap(func, it)

把 it 中的各个元素传给 func,产出结果;输入的可迭代对象应该产出可迭代的元素 iit,然后以 func(*iit) 这种形式调用 func

下面先单独演示 accumulate(it, [func]) 函数的用法吧,这个用法比较灵活

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

>>> import itertools

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

[5, 9, 11, 19, 26, 32, 35, 35, 44, 45]

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

[5, 4, 2, 2, 2, 2, 2, 0, 0, 0]

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

[5, 5, 5, 8, 8, 8, 8, 8, 9, 9]

>>> import operator

>>> list(itertools.accumulate(sample, operator.mul)) # 计算乘积

[5, 20, 40, 320, 2240, 13440, 40320, 0, 0, 0]

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

[1, 2, 6, 24, 120, 720, 5040, 40320, 362880]

接下来演示其他的映射生成器函数

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

[(1, 'a'), (2, 'l'), (3, 'b'), (4, 'a'), (5, 't'), (6, 'r'), (7, 'o'), (8, 'z')]

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

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

>>> list(map(operator.mul, range(11), [2, 4, 8])) # 计算两个可迭代对象对应位置上的元素之积, 元素最少的那个可迭代对象到头后就停止了

[0, 4, 16]

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

[(0, 2), (1, 4), (2, 8)]

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

['a', 'll', 'bbb', 'aaaa', 'ttttt', 'rrrrrr', 'ooooooo', 'zzzzzzzz']

>>> list(itertools.starmap(lambda a, b: b / a, enumerate(itertools.accumulate(sample), 1))) # 计算平均值

[5.0, 4.5, 3.6666666666666665, 4.75, 5.2, 5.333333333333333, 5.0, 4.375, 4.888888888888889, 4.5]

未完待续~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python生成器函数是一种特殊类型的函数,它使用 yield 关键字来返回一个迭代器。生成器函数可以用于按需生成值,而不是一次性生成所有值。 生成器函数的定义与普通函数类似,但使用 yield 语句而不是 return 语句来返回值。当调用生成器函数时,它会返回一个生成器对象,而不会立即执行函数体。每次迭代生成器对象时,函数会从上次暂停的位置继续执行,并返回 yield 语句后的值,直到没有更多的 yield 语句为止。 下面是一个简单的生成器函数示例,用于生成斐波那契数列: ```python def fibonacci(): a, b = 0, 1 while True: yield a a, b = b, a + b fib = fibonacci() for i in range(10): print(next(fib)) ``` 在上面的例子,定义了一个名为 fibonacci 的生成器函数。它使用 while 循环和 yield 语句来生成斐波那契数列的每个值。每次调用 next() 函数时,生成器会从上次暂停的位置继续执行,并返回 yield 语句后的值。 通过调用 fibonacci() 函数,我们得到了一个生成器对象 fib。然后使用 for 循环和 next() 函数迭代该生成器对象,打印出斐波那契数列的前 10 个数。 输出结果为: ``` 0 1 1 2 3 5 8 13 21 34 ``` 生成器函数的优点是它们可以按需生成值,而不需要一次性生成所有值,这在处理大量数据或无限序列时非常有用。由于生成器函数的特殊性质,它们具有较低的内存消耗,并且可以以一种更高效的方式实现迭代逻辑。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值