python基础---yield

来源:互联网 发布:淘宝发布宝贝添加规格 编辑:程序博客网 时间:2024/06/18 16:41

带有yield的函数在Python中被称为generator(生成器)。

yield演变过程

生成斐波拉切数列的例子说明.

清单1

直接用print,函数没有可复用性差。

def fab(max):    n,a,b=0,0,1    while n<max:        print b        a,b=b,a+b        n=n+1#输出>>>fab(5)>1>1>2>3>5

清单2

解决复用性差的问题,可以使用数列。但是运行内存会随着max增加而增加。

def fab(max):    n,a,b=0,0,1    L=[]    while n <max:        L.append(n)        a,b=b,a+b        n=n+1    return L#打印输出结果>>>for n in fab(5):    print n11235

其中输出最好不要使用List,而是通过中间结果,iterable对象来迭代:

for i in range(1000):pass#会生成一个1000个元素的Listfor i in xrange(1000):pass#不会生成一个1000个元素的List

清单3

将fab函数改写成一个支持iterable的class。

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():        if self.n<self.max:        r=self.b        self.a,self.b=self.b,self.a+self.b        self.b=self.n+1        return r    rasise StopInteration()#内存占用一直只是个常数>>>for n in Fab(5):    print n11235

清单4

为了更简洁,yield派上用场了。

def fab(max):    n,a,b=0,0,1    while n<max:        yield b        a,b=b,a+b        n=n+1#输出>>>for n in fab(5):    print n11235#也可以手动执行流程>>>f=fab(5)>>>f.next()1>>>f.next()1>>>f.next()2>>>f.next()3>>>f.next()5>>>f.next()Trackback (most recent call last):    File "<stdin>",line 1,in <modue>StopIteration

判断函数是否是一个特殊的迭代器generaor函数

注意:要区分fab和fab(5),fab是一个generator function,而fab(5)是调用fab返回的一个generator,好比类的定义和类的实例的区别.:

>>>from inspect import isgeneratorfunction>>>isgeneratorfunction(fab)True>>>import types>>>isinstance(fab,types.GeneratorType)False>>>isInstance(fab(5),types.GeneratorType)True#fab无法迭代,而fab(5)是可以迭代的>>>from collections import Iterable>>>isinstance(fab,Iterable)False>>>isinstance(fab(5),Iterable)True#每次调用fab函数都会生成一个新的generator实例,各个实例互相不影响>>>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

return 的作用

在一个generator function中,如果没有return,则默认执行至函数完毕,如果在执行过程中return ,直接抛出StopIteration终止迭代.

另一个读取文件例子

如果直接对文件对象调用read()方法,会导致不可预测的内存占用。好的方法是 利用固定长度缓冲区不断读取文件内容。

def read_file(fpath):    BLOCK_SIZE=1024    with open('/local/text.txt') as f:    block=f.read(BLOCK_SIZE)    if block:        yield block    else:        return
原创粉丝点击