生成器

如果读过前一节,那你应该已经知道“迭代器”指的是一种可以被“for”循环使用的对象。换句话说,迭代器就是遵循迭代协议的对象。 而生成器则是迭代器的一种更为简洁的实现方法。这种写法不再需要构造一个类,而只需编写一个函数,函数每次运行到“yield”语句时都会返回一个值。下面的例子是用生成器来依次生成两个数之间的整数:

def myrange(a, b):
    while a < b:
        yield a
        a += 1

与其他迭代器一样,生成器也可以用在“for”循环里:

>>> for value in myrange(1, 4):
... print(value)
...
1
2
3

生成器与迭代器大同小异:

>>> seq = myrange(1,3)
>>> next(seq)
1
>>> next(seq)
2
>>> next(seq)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

相比普通函数而言,生成器的要点在于“yield”这个关键字。“yield”关键字很像“return”关键字,但不同于“return”的是,它允许函数在返回一个值后重新恢复执行。换句话说,每当函数调用方想从生成器中取出下一个值的时候,Python 就会从“yield”关键字处唤醒这个已暂停的函数并继续往下执行,直到函数完全退出为止。

生成器函数当中同样可以调用其他生成器。比如,我们常用“range”函数来生成一组数字序列:

def squares(n):
    for value in range(n):
        yield value * value

生成器部分练习

  1. 写一个名为“squares”的生成器来生成(a)到(b)之间所有整数的平方,并用“for”循环来测试它。
  2. 用生成器来生成所有1到(n)之间的双数。
  3. 用生成器来生成所有1到(n)之间的单数。
  4. 编写一个生成器,按降序输出(n)到 0 之间的整数。
  5. 编写一个生成器,生成斐波那契数列当中小于(n)的数字。斐波那契数列的前几个数字是: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
  6. 编写一个生成器,生成 0 到(n)之间所有的相邻数对,形如 (0, 1), (1, 2), (2, 3)...

书籍推荐