python生成器及关键字yield

生成器是什么

生成器继承于迭代器,故生成器有迭代器的特性,是一个可以通过循环获取数据的对象

生成器保存的是生成数据的算法,不保存数据,迭代器是一组数据

python已有的列表生成器 list(range(1,11))无法解决内存限制的问题,所有产生的数据都在内存里,如果数据很大就会有内存溢出的问题

生成器是保存了生成数据的算法,不保存数据,同时也会保存游标的位置,记录当前取到哪个数据,下次继续从游标位置获取新数据

可以通过next()方法,一直通过生成器生成新数据,而不占用内存

生成器用到的关键字yield


yield用于给生成器函数返回数据,遇到yield后,函数暂停执行,将yield的值返回给调用方,下一次遇到next()时,再继续接着上一次执行的位置继续执行

def testfib():
    a = 0
    b = 1
    while True:
        yield b
print('b={}'.format(b))
        a,b = b,a+b
    return "done"
if __name__ == '__main__':
    a = testfib()
    print(next(a))
    print(next(a))
    print(next(a))
----------------
结果
1
b=1
1
b=1
2

testfib生成器保存了生成斐波那契数列数据的算法,
a= testfib() 定义了生成器a对象

main方法中调用了3次next(a),第一次next(a),程序返回b的值1,并暂停执行
第二次next(a),继续接着上一次的游标位置执行,先打印b=1,接着a,b= 1,1,下一次循环,遇到yield,返回当前b的值1
第三次next(a),继续接着上一次的游标位置执行,先打印b=1,接着a,b= 1,2,下一次循环,遇到yield,返回当前b的值2

* print(a)会打印<generator object testfib at 0x0000000002341DE0>,而不会打印done
只要在函数中有yield关键字,那么当前这个函数是属于生成器中保存的算法,算法实现的功能就是生成b


【说明】
遇到yield后,函数暂停执行,有一个例外:当直接把生成器转化为list、元祖时,会一直持续执行yield下面的语句,并不断产生数据

def testfib(num):
    a = 0
    b = 1
    n = 0
    while n<num:
        yield b
        a,b = b,a+b
        n +=1
    return "done"
if __name__ == '__main__':
    print(list(testfib(10)))
-------------
结果 [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]


main函数中直接将生成器转化为list,那么遇到yield,将数据返回后,也会继续执行下面的内容

 但是,如果生成器中循环没有结束条件,是while True ,那么使用(list(testfib(10))会无限循环打印列表数据,进入死循环


生成器用到的函数

  • next({generate})利用next让生成器 产生一个数据
  • {generate}.colse()遇到close,生成器终止产生数据,close后再次使用next()获取数据,会报错StopIteration
  • {generate}.seed(param) seed同next一样,也会让生成器 产生一个数据,不同的是,通过seed可以传递参数给生成器,且使用seed前需要先使用next 启动生成器
def testfib():
    a = 0
    b = 1
    n = 0
    num = yield
    while n< num:
        yield b
        print('n={}'.format(n))
        a,b = b,a+b
        n+=1
    return "done"
if __name__ == '__main__':
    a = testfib()
    next(a)
    print(a.send(3))
    print(a.send(3))
    print(a.send(3))
    print(a.send(3))
----------
返回:
1
n=0
1
n=1
2
n=2
Traceback (most recent call last):
  File "D:/python-workspace/pythontest/base/test1.py", line 983, in <module>
    print(a.send(3))
StopIteration: done


举例中通过seed传递参数3给生成器,生成器中判断当n<3时,允许产生数据
1.首先在seed传参前,调用next(a)启动生成器,代码执行到生成器的 num = yield这暂停,yield后没有跟数据,故本次next()不会产生数据
2.首次用a.seed(3)让生成器产生数据,程序接着num =yield执行,num被赋值为3,函数继续向下执行,n=0,n<num,yield 返回b
3.继续使用a.seed(3)再次成功产生2个数据,此时n=2
4.第4次使用a.seed(3)让生成器产生数据,接着上面一步继续执行,打印完n=2后,a,b进行复制,n+1,n=3,再去判断n<num不满足,终止生成数据,报错StopIteration

使用seed传参时,生成器及调用方有固定写法

def generator():
n= yield
while True:
{code with n}#这里是用到seed传递的n的代码
{code with return num}#这里是生成数据算法的部分,改变每次生成数据的值 如num= random()
yield num
return
if __name__ == '__main__':
#调用时先定义生成器对象
obj= generator()
next(obj)#启动生成器
a=obj.seed(5)#传递参数给生成器

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值