第六章生成器

生成器

>>> def make_counter(x):
...     print('entering make_counter')
...     while True:
...         yield x                    ①
...         print('incrementing x')
...         x = x + 1
... 
>>> counter = make_counter(2)          ②
>>> counter                            ③
<generator object at 0x001C9C10>
>>> next(counter)                      ④
entering make_counter
2
>>> next(counter)                      ⑤
incrementing x
3
>>> next(counter)                      ⑥
incrementing x
4
make_counter 中出现的 yield 命令的意思是这不是一个普通的函数。它是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。
调用该函数将返回一个可用于生成连续 x 值的 生成器【Generator】
为创建 make_counter 生成器的实例,仅需像调用其它函数那样对它进行调用。
注意该调用并不实际执行函数代码。可以这么说,是因为 make_counter() 函数的第一行调用了 print(),但实际并未打印任何内容。
该 make_counter() 函数返回了一个生成器对象。
next() 函数以一个生成器对象为参数,并返回其下一个值。
对 counter 生成器第一次调用 next() ,它针对第一条 yield 语句执行 make_counter() 中的代码,然后返回所产生的值。
在此情况下,该代码输出将为 2,因其仅通过调用 make_counter(2) 对生成器进行初始创建。
对同一生成器对象反复调用 next() 将确切地从上次调用的位置开始继续,直到下一条 yield 语句。
所有的变量、局部数据等内容在 yield 时被保存,在 next() 时被恢复。下一行代码等待被执行以调用 print() 以打印出 incrementing x 。
之后,执行语句 x = x + 1。然后它继续通过 while 再次循环,而它再次遇上的第一条语句是 yield x,该语句将保存所有一切状态,并返回当前 x 的值(当前为 3)。
第二次调用 next(counter) 时,又进行了同样的工作,但这次 x 为 4


斐波那契序列生成器

def fib(max):
    a, b = 0, 1          ①
    while a < max:
        yield a          ②
        a, b = b, a + b  ③
斐波那契序列是一系列的数字,每个数字都是其前两个数字之和。它从 0 和 1 开始,初始时上升缓慢,但越来越快。启动该序列需要两个变量:从 0 开始的 a,和从 1开始的 b 。
a 是当前序列中的数字,因此对它进行 yield 操作。
b 是序列中下一个数字,因此将它赋值给 a,但同时计算下一个值 (a + b) 并将其赋值给 b 以供稍后使用。注意该步骤是并行发生的;如果 a 为 3 且 b 为 5,那么 a, b = b, a + b 将会把 a 设置 5 (b 之前的值),将 b 设置为 8 ( a 和 b 之前值的和)。
>>> from fibonacci import fib
>>> for n in fib(1000):      ①
...     print(n, end=' ')    ②
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> list(fib(1000))          ③
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987]
可以在 for 循环中直接使用像 fib() 这样的生成器。for 循环将会自动调用 next() 函数,从 fib() 生成器获取数值并赋值给 for 循环索引变量。(n
每经过一次 for 循环, n 从 fib() 的 yield 语句获取一个新值,所需做的仅仅是输出它。一旦 fib() 的数字用尽(a 大于 max,即本例中的 1000), for 循环将会自动退出。
这是一个很有用的用法:将一个生成器传递给 list() 函数,它将遍历整个生成器(就像前例中的 for 循环)并返回所有数值的列表。





















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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值