如果你有坚定的信念你就不会迷茫。

Python: yield, iterator

上一篇 / 下一篇  2010-10-12 10:39:22 / 个人分类:Python

看到有很多人为yield写过blog. 其实我觉得就yield而言没有什么太多可以讲的。所以想把yield, generator, iterator一起来讲讲。

  iterator, 这个就是一个对象,实现了函数__iter__()和next()的对象。他不需要继承什么父类,只需要实现这两个函数的对象我们就可以把它当作 iterator来使用。如果要打印一串数,从0,1开始,后面的数是前面两个数的和(斐波那契数列)。这个时候我们可以很好的使用iterator来实 现:

  创建一个iterator类Fib,因为Fib类实现了函数__iter__()和next(),则被认为是一个iterator对象,可以通过for n in fib 来读取fib内的对象。每一次n都是从fib中取出一个值,然后再通过next函数取下面的值,一直这样下去。

  1. class Fib:  
  2.     def __init__(self, max):  
  3.         self.max = max  
  4.           
  5.     def __iter__(self):  
  6.         self.a = 0  
  7.         self.b = 1  
  8.         return self  
  9.       
  10.     def next(self):  
  11.         fib = self.a  
  12.         if fib > self.max:  
  13.             raise StopIteration # 如果已经大于最大值则抛出StopIteration异常  
  14.         self.a, self.b = self.b, self.a + self.b # 在return之前将self的值更新  
  15.         return fib  
  16.       
  17. if __name__=="__main__":  
  18.     fib = Fib(1000)  
  19.     for n in fib:  
  20.         print n  

   在上面的代码中我们可以看到,next函数中,必须要申明fib变量来保存self.a的值,然后才可以将self.b的值付给self.a.

   那如果我们使用yield返回来获得一个iterator则可以不用如此麻烦了,通过使用yield,fib函数可以认为是生成了一个generator. 这里我们每次返回了a以后,保留当前的状态继续执行一直到函数结束。所以我们不需要什么临时值,只需要在返回a后再执行即可

  1. def fib(max):    
  2.      a, b = 0, 1    
  3.      while a < max:    
  4.          yield a          
  5.          a, b = b, a + b    
  6.             
  7.       
  8. for n in fib(1000):  
  9.     print n  

   相比较list与iterator,可以知道iterator是不需要实现保存所有数据的,可以返回一个值处理一个。这样对于大数据量的时候可以节约很多内存。这大概就是在python3中range被xrange取代的原因吧。


TAG: Python python yield iterator

 

评分:0

我来说两句

日历

« 2024-04-28  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 20108
  • 日志数: 19
  • 建立时间: 2010-09-08
  • 更新时间: 2011-01-21

RSS订阅

Open Toolbar