~玉米糊~
慢慢来,也会很快。 非宁静无以志学,学什么都一样,慢慢打基础,找规律、认真、坚持,其余的交给时间。

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

posted on 2022-04-03 22:44  yuminhu  阅读(14)  评论(0编辑  收藏  举报