一、如何得到自定义的迭代器(生成器)
在函数内一旦存在yield关键字,调用函数并不会执行函数体代码
会返回一个生成器对象,生成器即自定义的迭代器
def func(): print('第一次') yield 1 print('第二次') yield 2 print('第三次') yield 3 print('第四次') g=func() # 此时并不运行函数体代码 print(g) # <generator object func at 0x000001D009181740> # 生成器就是迭代器 # g.__iter__() 均可调用 # g.__next__() # next()或g.__next__ 会触发函数体代码的运行,然后遇到yield停下来,将yield后的值 # 当做本次调用的结果返回 res1=g.__next__() # 打印第一次 print(res1) # 1 res2=g.__next__() # 打印第二次 print(res2) # 2 res3=g.__next__() # 打印第三次 print(res3) # 3 res4=g.__next__() # 打印第四次,并抛出异常StopIteration
二、应用案例
def my_range(start,end=None,step=1): # 满足 range(5)---》0 1 2 3 4 的情况 if end is None: output = 0 while output < start: yield output output += step else: # 满足 range(0,5,2) 设定步长输出 if step > 0: while start < end: yield start start += step # 满足range(5,0,-1) 步长为负时,逆走 if step < 0: while start > end: yield start start += step
测试:
# 测试: for i in my_range(5,0,-2): print(i,end=" ") print("") for i in range(5,0,-2): print(i,end=" ")
三、yield表达式
3.1 yield表达式介绍
一般形式:x = yield 返回值
使用 g.send(“xxx”)的方式给x传参,并且send在传参后自带next()功能
但一个生成器开始时,需要进行初始化(g.send(None) 或 next(g))。若不初始化,将会有以下报错:
3.2 yield表达式的使用案例
def dog(name): food_list=[] print('道哥%s准备吃东西啦...' %name) while True: # x拿到的是yield接收到的值 x = yield food_list # x = '肉包子' print('道哥%s吃了 %s' %(name,x)) food_list.append(x) # ['一根骨头','肉包子'] g=dog('alex') res=g.send(None) # next(g) print(res) # [] res=g.send('一根骨头') print(res) # ['一根骨头'] res=g.send('肉包子') print(res) # ['一根骨头', '肉包子'] g.close() g.send('1111') # 关闭之后无法传值 StopIteration
四、总结yield
有了yield关键字,我们就有了一种自定义迭代器的实现方式。yield可以用于返回值,但不同于return。
函数一旦遇到return就结束了,而yield可以保存函数的运行状态挂起函数,用来返回多次值
有了yield表达式,我们可以使函数的运行状态挂起,随时待命,等待我们再次传值给他。