Python3.x生成器yield表达式与__next__、send方法理解
当一个生成器函数被调用时,它将返回一个名为生成器的迭代器。 然后这个生成器将控制生成器函数的执行。 执行过程会在这个生成器的某个方法被调用时开始。 这时,函数会执行到第一个 yield 表达式,在那里它将再次被挂起,向生成器的调用方返回 yield_list 的值,或者如果 yield_list 被省略则返回 None。————Python官方文档-6.2.9. yield 表达式
生成器函数
这是当一个带返回值的普通函数
def test_fun():
return 1
>>print(test_fun())
1
将return换成yield之后, 这个函数就变成了一个生成器函数(不是定义)
def generator_fun():
val1 = yield 1
val2 = yield 2
>>g = generator_fun() // 生成器函数调用时返回生成器
>>print(next(g)) // 控制生成器函数的执行
1
>>print(g.send(None)) // 控制生成器函数的执行
2
该函数被调用的时候并不直接返回yield后面的值,而是返回一个名为生成器的可迭代对象,需要使用内置函数next()或者生成器对象方法send()控制生成器函数本身的执行过程。
注意:
- yield在函数体中可以有多个,但是函数中的return在同一分支的代码块中只能有一个
- yield及其“返回值” 组成的整体是一个有值的表达式,被称为yield表达式,表达式的值可以从外面传入(即生成器对象send()传入的值);如果没有从外面传入,则表达式的值为None
生成器函数的开始、暂停和恢复
生成器函数的开始执行
生成器函数开始执行的方式有两种:
- 使用next()函数,将生成器作为参数传入:
该函数底层会调用生成器对象内部的__next__()方法
g = generator_fun() // 生成器函数调用时返回生成器
next(g) // 生成器开始执行
- 使用生成器对象的send()方法,参数必须为None
g = generator_fun() // 生成器函数调用时返回生成器
g.send(None) // 生成器开始执行
生成器函数的暂停
生成器执行的特点是:执行流运行至yield时,将yield返回值返回给调用方后,函数执行的状态会被保存,然后函数执行过程被暂停
生成器函数的恢复
生成器执行恢复的方式和开始执行的调用方式相似
- 使用next()函数,将生成器作为参数传入:
该函数底层会调用生成器对象内部的__next__()方法, 生成器从上一次暂停的位置继续向下执行
g = generator_fun() // 生成器函数调用时返回生成器
next(g) // 生成器从上一次暂停的位置继续执行
- 使用生成器对象的send()方法,参数可以是指定的值
def generator_fun():
val1 = yield 1
print("val1 = ", val1)
val2 = yield 2
print("val2 = ", val2)
>>g = test_fun() // 生成器函数调用时返回生成器
>>print(g.send(None)) // 生成器开始执行
1
>>print(g.send(2)) // 生成器继续执行,yield 1的值是传入的2, 因此, val1===2
val1 = 2
2
>>print(g.send(3)) // 生成器继续执行,yield 2的值是传入的3, 因此, val2===3
val2 = 3
StopIteration
使用send(value)传入指定值后,该值会被赋值给yield表达式, 然后复制给表达式左侧的值,最后恢复执行流,继续向下执行,直到yield返回值,或者抛出StopIteration异常。
本文来自博客园,作者:昆仑路远,转载请注明原文链接:https://www.cnblogs.com/shiyee/p/19336032
浙公网安备 33010602011771号