生成器哒!
生成器
生成器就是一个自定义的迭代器
生成器就是迭代器
生成器的使用
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
会返回一个生成器对象,生成器即自定义的迭代器
def func(): print('第一次') yield 1 print('第二次') yield 2 print('第三次') yield 3 print('第四次') g=func() print(g) # 生成器就是迭代器 g.__iter__() # g.__next__()会触发函数体代码的运行,然后遇到yield停下来,将yield后的值 # 当做本次调用的结果返回
会触发函数体代码的运行,然后遇到yield停下来,将yield后的值当做本次调用的结果返回
res1=g.__next__() print(res1) res2=g.__next__() print(res2) res3=g.__next__() print(res3) res4=g.__next__() len('aaa') # 'aaa'.__len__() next(g) # g.__next__() iter(可迭代对象) # 可迭代对象.__iter__()
应用案列
def my_range(start,stop,step=1): print('start...') while start < stop: yield start start+=step print('end....') g=my_range(1,5,2) print(next(g)) # start... # 1 print(next(g)) # 3 print(next(g)) # end.... # StopIteration for n in my_range(1,7,2): print(n) # start... # 1 # 3 # 5 # end....
总结yield
-
有了yield关键字,我们就有了一种自定义迭代器的实现方式。
-
yield可以用于返回值,但不同于return,函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
生成器补充!!!
yield表达式应用
在函数内可以采用表达式形式的yield
def eater(): ... print('Ready to eat') ... while True: ... food=yield ... print('get the food: %s, and start to eat' %food)
可以拿到函数的生成器对象持续为函数体send值,如下
>>> g=eater() # 得到生成器对象 >>> g <generator object eater at 0x101b6e2b0> >>> next(e) # 需要事先”初始化”一次,让函数挂起在food=yield,等待调用g.send()方法为其传值 Ready to eat >>> g.send('包子') get the food: 包子, and start to eat >>> g.send('鸡腿') get the food: 鸡腿, and start to eat
针对表达式形式的yield,生成器对象必须事先被初始化一次
让函数挂起在food=yield的位置,等待调用g.send()方法为函数体传值,g.send(None)等同于next(g)。
我们可以编写装饰器来完成为所有表达式形式yield对应生成器的初始化操作,如下
def init(func): def wrapper(*args,**kwargs): g=func(*args,**kwargs) next(g) return g return wrapper @init def eater(): print('Ready to eat') while True: food=yield print('get the food: %s, and start to eat' %food)
表达式形式的yield也可以用于返回多次值,即变量名=yield 值
的形式,如下
>>> def eater(): ... print('Ready to eat') ... food_list=[] ... while True: ... food=yield food_list ... food_list.append(food) ... >>> e=eater() >>> next(e) Ready to eat [] >>> e.send('玩具车') ['玩具车'] >>> e.send('变形金刚') ['玩具车', '变形金刚'] >>> e.send('奥特曼') ['玩具车', '变形金刚', '奥特曼']