1、生成器与yield
若函数体包含yield关键字,再调用函数,并不会执行函数体代码,只是得到的返回值即生成器对象
def my_range(start,stop,step=1): while start < stop: yield start start += step g = my_range(1,10,2) print(g) while True: try: print(g.__next__()) #yield用于返回值 except(StopIteration): break
执行结果:
<generator object my_range at 0x000001523374A5C8> 1 3 5 7 9
总结:
生成器内置有__iter__和__next__方法,所以生成器本身就是一个迭代器
有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
2、yield表达式应用
(1)yield基本应用
在函数内可以采用表达式形式的yield,可以拿到函数的生成器对象持续为函数体send值,如下
def eater(): print('Ready to eat') while True: food=yield print('get the food: %s, and start to eat' %food) g=eater() # 得到生成器对象 print(g) print(next(g)) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值 g.send('包子') g.send('鸡腿')
运行结果
<generator object eater at 0x00000219AA1CA5C8> Ready to eat None get the food: 包子, and start to eat get the food: 鸡腿, and start to eat
针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,send不仅是对yield传值,还有next方法的作用,传值为None那么g.send(None)等同于next(g)。
(2)装饰器初始化生成器
def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) # 函数中有关键字yield,因此函数不会执行,而是直接返回一个生成器对象 next(g) # 这步必须要做,执行函数体代码,并让eater函数挂起在food = yield处 return g # 返回生成器对象,让用户能够调用,当然这也是装饰器必要的返回值伪装。 return wrapper @init def eater(): print('Ready to eat') food_list = [] while True: food = yield food_list #左边send传值,右边next或send返回值 food_list.append(food) g = eater() g.send('阆中牛肉面') g.send('成都冒菜') g.send('成都羊肉汤锅') res = g.send('酸辣粉') print(res)
执行结果:
Ready to eat ['阆中牛肉面', '成都冒菜', '成都羊肉汤锅', '酸辣粉']
————————————————
版权声明:本文为CSDN博主「凤求凰的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44571270/article/details/106005998