# Python 学习笔记之 -- yield

2017/07/08 20:31

## 如何生成斐波那契數列

 1 2 3 4 5 6 def fab(max):     n, a, b = 0, 0, 1     while n < max:         print b         a, b = b, a + b         n = n + 1

 1 2 3 4 5 6 >>> fab(5)  1 1 2 3 5

 1 2 3 4 5 6 7 8 def fab(max):     n, a, b = 0, 0, 1     L = []     while n < max:         L.append(b)        a, b = b, a + b         n = n + 1     return L

 1 2 3 4 5 6 7 8 >>> for n in fab(5):  ...     print n  ... 1 1 2 3 5

 1 for i in range(1000): pass

 1 for i in xrange(1000): pass

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Fab(object):       def __init__(self, max):         self.max = max         self.n, self.a, self.b = 0, 0, 1       def __iter__(self):         return self       def next(self):         if self.n < self.max:             r = self.b             self.a, self.b = self.b, self.a + self.b             self.n = self.n + 1             return r         raise StopIteration()

Fab 类通过 next() 不断返回数列的下一个数，内存占用始终为常数：

 1 2 3 4 5 6 7 8 >>> for n in Fab(5):  ...     print n  ... 1 1 2 3 5

 1 2 3 4 5 6 7 8 9 def fab(max):      n, a, b = 0, 0, 1      while n < max:          yield b          # print b          a, b = b, a + b          n = n + 1    '''

 1 2 3 4 5 6 7 8 >>> for n in fab(5):  ...     print n  ... 1 1 2 3 5

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 >>> f = fab(5)  >>> f.next()  1 >>> f.next()  1 >>> f.next()  2 >>> f.next()  3 >>> f.next()  5 >>> f.next()  Traceback (most recent call last):   File "<stdin>", line 1, in <module> StopIteration

yield 的好处是显而易见的，把一个函数改写为一个 generator 就获得了迭代能力，比起用类的实例保存状态来计算下一个 next() 的值，不仅代码简洁，而且执行流程异常清晰。

 1 2 3 >>> from inspect import isgeneratorfunction  >>> isgeneratorfunction(fab)  True

 1 2 3 4 5 >>> import types  >>> isinstance(fab, types.GeneratorType)  False >>> isinstance(fab(5), types.GeneratorType)  True

fab 是无法迭代的，而 fab(5) 是可迭代的：

 1 2 3 4 5 >>> from collections import Iterable  >>> isinstance(fab, Iterable)  False >>> isinstance(fab(5), Iterable)  True

 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 >>> f1 = fab(3)  >>> f2 = fab(5)  >>> print 'f1:', f1.next()  f1: 1  >>> print 'f2:', f2.next()  f2: 1  >>> print 'f1:', f1.next()  f1: 1  >>> print 'f2:', f2.next()  f2: 1  >>> print 'f1:', f1.next()  f1: 2  >>> print 'f2:', f2.next()  f2: 2  >>> print 'f2:', f2.next()  f2: 3  >>> print 'f2:', f2.next()  f2: 5

## 另一个例子

 1 2 3 4 5 6 7 8 9 def read_file(fpath):     BLOCK_SIZE = 1024     with open(fpath, 'rb') as f:         while True:             block = f.read(BLOCK_SIZE)             if block:                 yield block             else:                return

0
0 收藏

0 评论
0 收藏
0