#python入门5#高级特性-生成器

2016-11-29  本文已影响8人  MORESIR

要创建一个generator,有如下方法:

1. 把列表生成式的 [ ] 改为 ( ),即可
  >>> L=[x*x for x in range(10)]
  >>> L
  [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
  >>> g = (x * x for x in range(10))
  >>> g
  <generator object <genexpr> at 0x1022ef630>

创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。
可以使用next()打印generator的每一个元素

  >>> next(g)
  0
  >>> next(g)
  1
  ......一直重复
  >>> next(g) #最后一个
  Traceback (most recent call last): File "<stdin>", line 1, in  <module> StopIteration

generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

当然,上面这种不断调用next(g)实在是太变态了,正确的方法是使用for循环,因为generator也是可迭代对象:

  >>> g=(x*x for x in range(6))
  >>> for n in g:
  ...          print(n)
0
1
4
9
16
25
36

我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误

2 . 如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:

1, 1, 2, 3, 5, 8, 13, 21, 34, ...

斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:

  def fib(max): 
        n, a, b = 0, 0, 1 
        while n < max: 
              print(b) 
              a, b = b, a + b 
              n = n + 1 
        return 'done'

注意,赋值语句:
a, b = b, a + b
相当于:
t = (b, a + b) # t是一个tuplea = t[0]b = t[1]
但不必显式写出临时变量t就可以赋值。

  >>> fib(6)
  1
  1
  2
  3
  5
  8
  'done'

细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。
** 上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了** :

  def fib(max): 
        n, a, b = 0, 0, 1 
        while n < max: 
            yield b 
            a, b = b, a + b 
            n = n + 1 
        return 'done'

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator

  >>> for n in fib(6):
  ...       print(n)
  ...
  1
  1
  2
  3
  5
  8

但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中

>>> g = fib(6)
>>> while True:
...    try:
...      x = next(g)
...      print('g:', x)
...    except StopIteration as e:
...       print('Generator return value:', e.value)
...       break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
学习来源于廖雪峰教程
上一篇 下一篇

猜你喜欢

热点阅读