生成器

生成器

什么是生成器?

生成的工具

生成器是一个'自定义'的迭代器,本质上是一个迭代器

#因为生成器内置有.__iter__()和.__next__()方法,所以生成器本身就是一个迭代器
print(res.__iter__())
print(res.__next__())
#结果为
<generator object my_range at 0x0000020BCB802348>
1
如何实现生成器?

但凡在函数内部定义了yield,调用函数时函数体代码不会执行,会返回一个结果,该结果就是一个生成器

def my_range(start, stop, step=1): #定义函数
    print('start...')              #打印内容为start    
    while start < stop:            #进行加了判断条件的while循环
        yield start                #返回一个结果,即生成器
        start += step   #每次取出的值都是在上一个值的基础上加上步长step


res = my_range(1, 5)    #定义变量名res等于调用函数my_range得到的结果,结果就是一个生成器对象
print(res)
#结果为
<generator object my_range at 0x0000015710A42348>
#因为生成器的本质上是迭代器,所以我们可以用迭代取值的方式取值,即通过.__next__()
print(res.__next__())
#还可以直接用next取值
print(next(res))
print(next(res))
print(next(res))
print(next(res))
#结果为
start...
1 #触发函数执行直到遇到yield则停止,将yield后的值返回,并在当前位置挂起函数
2 #调用next(res),函数从上次暂停的位置继续执行,直到重新遇到yield...
3 # 周而复始...
4 # 周而复始...
StopIteration # 触发函数执行没有遇到yield则无值返回,即取值完毕抛出异常结束迭代
yield

有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值

每一次yield都会往生成器对象中添加一个值

def eater():
    print('Ready to eat')
    while True:
        food = yield
        print(f'get the food:%s,and start to eat' % food)


g = eater() # 得到生成器对象
print(g) 
next(g) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调g.send()方法为其传值
next(g)
g.send('包子')
#结果为
<generator object eater at 0x000001F0711121C8>
Ready to eat
get the food:None,and start to eat
get the food:包子,and start to eat
#PS:针对表达式形式的yield,生成器对象必须事先被初始化一次,让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)。
def init(func):
    def wrapper(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        next(g) #next(g)相当于g.send(None)
        g.send('鸡腿')
        return g
    return wrapper



@init
def eat():
    print('Ready to eat')
    while True:
        food = yield
        print('get the food:%s, and start to eat' % food)
eat()
#输出结果为
Ready to eat
get the food:None, and start to eat
get the food:鸡腿, and start to eat

PS:yield只能在函数内部定义

​ yield可以保存函数的暂停状态

yield和return

相同点:返回值的个数都是无限制的

不同点:return只能返回一次值,yield可以返回多个值

#yield也可以用于返回多次值,即变量名=yield 值的形式
def eater():
    print('Ready to eat')
    food_list = []
    while True:
        food = yield food_list
        food_list.append(food)


e = eater()
next(e)
print(e.send('牛肉'))
print(e.send('羊肉'))
print(e.send('红烧肉'))
#结果为
Ready to eat
['牛肉']
['牛肉', '羊肉']
['牛肉', '羊肉', '红烧肉']
原文地址:https://www.cnblogs.com/a736659557/p/11892371.html