生成器

如果你读了之前的章节,你就会知道得带器是一个可以被“for”循环使用的对象。换句话说,迭代器就是遵循迭代协议的对象。
Python的生成器则是使用更简单的方法来部署迭代器的一个东西。不同于类,生成器是一个函数,每次遇到“yield”关键字时都会返回一个值。下面的例子是用生成器来生成两个数之间的数:

  1. def myrange(a, b):
  2. while a < b:
  3. yield a
  4. a += 1

像迭代器一样,生成器可以用在“for”循环里:

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

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

  1. >>> seq = myrange(1,3)
  2. >>> next(seq)
  3. 1
  4. >>> next(seq)
  5. 2
  6. >>> next(seq)
  7. Traceback (most recent call last):
  8. File "<stdin>", line 1, in <module>
  9. StopIteration

对于生成器来说,真正有点意思的地方是“yield”关键字。“yield”关键字很像“return”关键字,但不同于“return”的是,它允许函数恢复执行。换句话说,生成器所生成的每个值都是被需要的。Python见到“yield”关键字就会唤醒并恢复执行这个函数,如果函数还没有完全退出的话。
生成器函数可以用在其他函数内,比如,配合“range”函数来生成一组数字再平常不过了:

  1. def squares(n):
  2. for value in range(n):
  3. yield value * value

生成器部分练习

  1. 写一个名为“squares”的生成器来生成(a)到(b)之间所有数的平方。使用“for”循环来测试。
  2. 创建一个生成器来生成所有1到(n)之间的双数。
  3. 创建另一个生成器来生成所有1到(n)之间的单数。
  4. 创建一个生成器来生成所有(n)到0之间的数。
  5. 创建一个生成器来生成斐波那契数列。范围是第一个数字到(0)。斐波那契数列的前几个数字是: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, …
  6. 创建一个生成器来生成所有0到(n)之间所有的连续对。如(0, 1), (1, 2), (2, 3)….