python yiled
yield
yield
Table of Contents
1 yield 使用方法(生成器)
1.1 当方法中包含yield时,该方法为Generator,直接调用不会执行,只有循环或next()可行
def show_yield(num): yield 12 show_yield(1) 这样没有反应 只有这样 for i in show_yield(1): print(i) # 这样会打印出12
1.2 next() 会将带有yield的方法执行,并运行到第一次出现yield的部分,然后再次调用时
#执行到下一个,直到没有yield之后抛出异常 def show_yield_next(): print('before yield') yield 1 print('first yield') yield 2 print('last yield') a = show_yield_next() """ b = show_yield_next() 在这里因为每次调用该函数会返回一个不同的对象,导致如果 这样写的话会一直只调用第一句话 next(show_yield_next()) next(show_yield_next()) next(show_yield_next()) 会显示三次一样的内容 必须先将对象赋值给一个变量,之后只对该变量进行操作 """ a1 = next(a) # before yield a1=1 a2 = next(a) # first yield a2=2 a3 = next(a) # last yield 并抛出异常
1.3 send(self,value)与next类似,但是会传入一个值给yield表达式
#注意,被传入的值是yield表达式的返回值,而不是yield的值(这点与Ruby不同) #例如: def show_send_to_yield(): print('before') yield_value = yield print(yield_value) yield_value = yield 10 print(yield_value) yield_value = yield '测试' print(yield_value) ssy = show_send_to_yield() next(ssy) # 必须先执行这一步,将执行位置调整至yield语句部分 ssy.send(100) # 可以看到,yield的后面不论是什么,都会将yield_value的值赋为传入的值 # *但是* 当没有使用send对yield赋值时,yield的整体值就是它的参数 # x = yield 10 没有send时,x就是10 #所以如果想要传递一个函数进去,不需要注意yield后面的值,但是在调用时需要记得给参数,如: ssy.send(lamdba x : print(x)) #在调用时要注意给一个参数,如: yield_value(10) #也可以设置一个标识,来使用for循环,当在某步之后执行传递参数的工作 #例如,在某个yield使用完毕之后赋值为指定参数 def show_for_in_yield(): yield_value = yield 'send' print(yield_value) for i in ssy: if i == 'send': ssy.send(100)
2 有代码如下:
def show_for_in_yield(): yield_value1 = yield 'send' #1 print("yield1 :"+str(yield_value1)) yield_value2 = yield 'sen' #2 print("yield2 :"+str(yield_value2)) sfy = show_for_in_yield() try: for i in sfy: #a if i == 'send': #x=sfy.send(100) #b pass print(i) except Exception as exp: print(exp) #因为生成器每次只生成当前使用的部分,所以在第一次进入for时只有一个,执行完毕#1后#2生成,执行2
2.1 通过单步调试发现for循环调用生成器的过程为(注释代码b)(将执行顺序看做指针)
第一步:在a处进入生成器执行#1 并获得yield的值,此时,指针指向#1 执行之后的循环,输出值'send' 第二步:在a处重新进入生成器,并且将#1处的yield值置为None 执行生成器中下一步,输出yield1的值None 第三步:在#2处进入循环,重复上次动作
2.2 当代码b被打开时
第一步:在a处进入生成器执行#1 并获得yield的值,此时,指针指向#1 并进入生成器,并对yield赋值 第二步:执行#2时,因为上次是跳转到生成器中的,所以直接执行上次未完成的输出语句, 输出了第一个yield的值,并进入下个循环 导致在循环体中没有执行第二个yield,只执行了半个循环体 若想输出完整的内容,需要将for改造如下
for i in sfy: if i == 'send': x=sfy.send(100) print(i) print(x) else: print(i)