每次只生成一个值,而不是直接创建大的元组,节省内存消耗。
先看一个交互式例子。
1 | def make_counter(x): |
make_counter
中出现的 yield 命令的表示这不是一个普通的函数,而是一个一次生成一个值的特殊类型函数。调用该函数将返回一个可用于生成连续 x 值的 生成器【Generator】 。
为创建 make_counter
生成器的实例,仅需像调用其它函数那样对它进行调用。注意该调用并不完全执行函数里的指令,由上例可见它并不指定第一行的print
指令。
next()
函数以一个生成器对象为参数,并返回其下一个值。对 counter 生成器第一次调用 next()
,它针对第一条 yield 语句执行 make_counter()
中的代码,然后返回所产生的值。在此情况下,该代码输出将为 2,因其仅通过调用 make_counter(2)
对生成器进行初始创建。
对同一生成器对象反复调用 next()
将确切地从上次调用的位置开始继续,直到下一条 yield
语句。所有的变量、局部数据等内容在 yield
时被保存,在 next()
时被恢复 。下一行代码等待被执行以调用 print()
打印出 incrementing x
。之后,执行语句 x = x + 1。然后它继续通过 while
再次循环,而它再次遇上的第一条语句是 yield x
,该语句将保存所有一切状态,并返回当前 x 的值。
yield
暂停一个函数。next()
从其暂停处恢复其运行。
由于 make_counter
设置了一个无限循环,理论上可以永远执行该过程,它将不断递增 x 并输出数值。还是让我们看一个更加实用的生成器用法。
1 | def fib(max): |
斐波那契序列是一系列的数字,每个数字都是其前两个数字之和。它从 0 和 1 开始,初始时上升缓慢,但越来越快。启动该序列需要两个变量:从 0 开始的 a,和从 1 开始的 b 。
a 是当前序列中的数字,因此对它进行 yield
操作。b 是序列中下一个数字,因此将它赋值给 a,但同时计算下一个值 (a + b) 并将其赋值给 b 以供稍后使用。
因此,现在有了一个连续输出斐波那契数值的函数。当然,还可以使用递归来完成该功能,但这个方式更易于阅读。同样,它也与 for
循环合作良好。
1 | from fibonacci import fib |
可以在 for 循环中直接使用像 fib() 这样的生成器。for 循环将会自动调用 next() 函数,从 fib() 生成器获取数值并赋值给 for 循环索引变量。
生成表达式类似生成器函数,只不过它不是函数。
1 | 'E', 'D', 'M', 'O', 'N', 'S', 'R', 'Y'} unique_characters = { |
tuple()
, list()
, 或者 set()
迭代所有的值并且返回元组,列表或者集合。在这种情况下,你不需要一对额外的括号 — 将生成器表达式 ord(c) for c in unique_characters
传给 tuple()
函数就可以了, Python 会推断出它是一个生成器表达式。