>>spam

python中的生成器(generator)

系统 1918 0

生成器是python中一个非常酷的特性,python 2.2中引入后在2.3变成了标准的一部分。它能够让你在许多情况下以一种优雅而又更低内存消耗的方式简化无界(无限)序列相关的操作。

生成器是可以当做iterator使用的特殊函数,它功能的实现依赖于关键字yield,下面是它如何运作一个简单的演示:

>>> def spam():
yield " first "
yield " second "
yield " third "


>>> spam
< function spam at 0x011F32B0 >
>>> for x in spam():
print x


first
second
third
>>> gen = spam()
>>> gen
< generator object spam at 0x01220B20 >
>>> gen.next()
' first '
>>> gen.next()
' second '
>>> gen.next()
' third '

在函数spam()内定义了一个生成器,但是对spam()的调用永远只能获得一个单独的生成器对象,而不是执行函数里面的语句,这个对象(generator object)包含了函数的原始代码和函数调用的状态,这状态包括函数中变量值以及当前的执行点——函数在yield语句处暂停(suspended),返回当前的值并储存函数的调用状态,当需要下一个条目(item)时,可以再次调用next,从函数上次停止的状态继续执行,知道下一个yield语句。

生成器和函数的主要区别在于函数 return a value,生成器 yield a value同时标记或记忆 point of the yield 以便于在下次调用时从标记点恢复执行。  yield  使函数转换成生成器,而生成器反过来又返回迭代器。

有三种方式告诉循环生成器中没有更多的内容:

  1. 执行到函数的末尾("fall off the end")
  2. 用一个return语句(它可能不会返回任何值)
  3. 抛出StopIteration异常

一个 经典的例子 是和C语言中的static语句相比较:在Python没有明确支持的所谓static变量,但是在函数之间相互调用时,生成器能让你能以一个更优雅的方式实现类似的效果:

在C语言中  fibonacci 函数的实现:

#include < stdio.h >

int main() {
printf(
" 0\n " );
printf(
" 1\n " );
while ( 1 )
printf(
" %d\n " ,fib());
/* for test use */
// int i=0;
// while(i<20){
// i++;
// printf("%d\n", fib());}
}

int fib() {
static unsigned first = 0 ,second = 1 ,next,retval;

next
= first + second;
retval
= next;
first
= second;
second
= next;

return retval;

}

python实现:

# !/usr/bin/env python
#
-*- coding: utf-8 -*-
#
filename: fib.py

def fib():
first
= 0
second
= 1
yield first
yield second

while 1 :
next
= first + second
yield next
first
= second
second
= next

运行:

>>> from fib import fib
>>> fib()
< generator object fib at 0xb76fcfcc >
>>> import itertools
>>> list(itertools.islice(fib(), 10 ))
[0,
1 , 1 , 2 , 3 , 5 , 8 , 13 , 21 , 34 ]

也可以用如下方式截取一部分输出(但建议使用 itemtools 模块):

>>> for (i, num) in zip(range( 10 ),fib()):
...
print num

上述 fibonacci 函数的实现看起来较为繁琐,更加简捷优雅的实现如下:

# !/usr/bin/env python
#
-*- coding: utf-8 -*-
#
filename: fib.py

def fib():
first, second
= 0, 1
while 1 :
yield second
first, second
= second, first + second

注意:但是在C语言中由于static的特性,在一个函数体内当需要产生多组 fibonacci 数列时可能就需要定义相同的诸如fib1() fib2() fib3()的函数。python中可以利用上述函数构造任意多个独立的生成器对象。

至于生成器(generator)应该使用在哪些方面以便更好地节省内存——你可以使用在需要计算列表的值但是每次只需要访问一个item的地方,和预先计算好将其存储在一个列表里相比,生成器在运行中逐个计算其值(computes the values on the fly)。

python中的生成器(generator)


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论