python基础---yield

带有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 n
1
1
2
3
5

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

for i in range(1000):pass#会生成一个1000个元素的List
for 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 n
1
1
2
3
5

清单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 n
1
1
2
3
5
#也可以手动执行流程
>>>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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值