python yiled

 

yield

yield

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)

2.3 所以在循环循环体时注意不要对循环体进行操作,如确实需要赋值等操作为保险起见手动调用next与send

Author: vz liū

Created: 2017-03-22 Wed 21:07

Emacs 25.1.1 (Org mode 8.2.10)

Validate

posted @ 2017-03-22 21:11  自动化昵称  阅读(1404)  评论(0编辑  收藏  举报