生成器

生成器就是一个函数,python中带yield关键字的函数就是一个生成器。yield语句就是返回一个对象(值),和普通的函数用return返回值不同如果想取得值,那得调用next()函数,如:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. c = h() #h()包含了yield关键字    
  2. #返回值    
  3. c.next()  


每当调用一次迭代器的next函数,生成器函数运行到yield之处,返回yield后面的值且在这个地方暂停,所有的状态都会被保持住,直到下次next函数被调用,或者碰到异常循环退出。

生成器在内部记住了记住上一次返回时在函数体中的位置。对生成器函数的第二次(或第 n 次)调用跳转至该函数中间,而上次调用的所有局部变量和函数参数都保持不变。生成器不仅“记住”了它的数据状态;生成器还“记住”了它在流控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

其实说白了就是,生成器记录了上次调用的数据与执行流程。
[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. def fib(max):    
  2.     a, b = 11    
  3.     while a < max:    
  4.         yield a #generators return an iterator that returns a stream of values.    
  5.         a, b = b, a+b  
  6.         print "a=",a,"b=",b    
  7. for n in fib(15):    
  8.     print n    

通过使用生成器的语法,可以免去写迭代器类的繁琐代码,如,上面的例子使用迭代类来实现,代码如下:

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class Fib:    
  2.     def __init__(self, max):    
  3.         self.max = max    
  4.     def __iter__(self):       #定制可迭代类重载__iter__  
  5.         print "iter"    
  6.         self.a = 0    
  7.         self.b = 1    
  8.         return self    
  9.     def next(self):           #定制可迭代类重载next()    
  10.         print "next"    
  11.         fib = self.a    
  12.         if fib > self.max:    
  13.             raise StopIteration    
  14.         self.a, self.b = self.b, self.a + self.b    
  15.         return fib    
  16.   
  17. for i in Fib(5):  
  18.     print i  




[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #yield其他例子展示:排列,组合  
  2. #生成全排列      
  3. def perm(items, n = None):    
  4.     if n is None:    
  5.         n = len(items)    
  6.     for i in range(len(items)):    
  7.         v = items[i:i+1]    
  8.         if n==1:    
  9.             yield v    
  10.         else:    
  11.             rest = items[:i] + items[i+1:]    
  12.             for p in perm(rest, n-1):    
  13.                 yield v + p  
  14.   
  15. def comb(items, n = None):    
  16.     if n is None:    
  17.         n = len(items)    
  18.     else:    
  19.         for i in range(len(items)):    
  20.             v = items[i:i+1]    
  21.             if 1 == n:    
  22.                 yield v    
  23.             else:    
  24.                 rest = items[i+1:]    
  25.                 for c in comb(rest, n-1):    
  26.                     yield v + c    

生成器语法
生成器表达式是在python2.4中引入的,当序列过长, 而每次只需要获取一个元素时,应当考虑使用生成器表达式而不是列表解析。

生成器表达式的语法和列表解析一样,只不过生成器表达式是被()括起来的,而不是[],如下: 

[python]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. (expr for iter_var in iterable)   
  2. (expr for iter_var in iterable if cond_expr)   
  3.   
  4. >>> L= (i + 1 for i in range(10if i % 2)   
  5. >>> L   
  6. <generator object <genexpr> at 0xb749a52c>   
  7. >>> L1=[]   
  8. >>> for i in L:   
  9. ... L1.append(i)   
  10. ...   
  11. >>> L1   
  12. [246810]   

生成器表达式并不真正创建数字列表, 而是返回一个生成器,这个生成器在每次计算出一个条目后,把这个条目“产生”(yield)出来。
生成器表达式使用了“惰性计算”,只有在检索时才被赋值( evaluated),所以在列表比较长的情况下使用内存上更有效。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值