生成器
生成器
什么是生成器?
生成的工具
生成器是一个'自定义'的迭代器,本质上是一个迭代器
#因为生成器内置有.__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://home.cnblogs.com/u/a736659557/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。