带有 yield
的函数在 Python
中被称之为 generator
(生成器),yield
语句一般与循环体共同使用,进而实现类似迭代的效果。
下面以生成斐波那契数列为例,理解yield
的作用:
def fab(max):
n, a, b = 0, 0, 1
while n < max:
yield b # 使用 yield
a, b = b, a + b
n = n + 1
for m in fab(5):
print(m)
输出:
1
1
2
3
5
简单地讲,yield
的作用就是把一个函数变成一个 generator
,带有 yield
的函数不再是一个普通函数,Python
解释器会将其视为一个 generator
,调用 fab(5)
不会执行 fab
函数,而是返回一个 迭代(iterable
) 对象。
在 for
循环执行时,每次循环都会执行 fab
函数内部的代码,执行到 yield b
时,fab
函数就返回一个迭代值,下次迭代时,代码从 yield b
的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield
。
结合上述函数,对其执行过程进行拆解:
- 第1次
for
循环,调用fab(5)
函数,运行while
循环体,运行至yield b
,此时 n = 0 , a = 0 , b = 1 n=0,a=0,b=1 n=0,a=0,b=1,返回b
值并暂停,此时循环m
得到b
值,打印m
,为1
; - 第2次
for
循环,接着a, b = b, a + b
向下运行,得到 a = 1 , b = 1 , n = 1 a=1,b=1,n=1 a=1,b=1,n=1,经while
条件再次运行至yield b
,返回b
值并暂停,打印m
,为1
; - 第3次
for
循环,接着a, b = b, a + b
向下运行,得到 a = 1 , b = 2 , n = 2 a=1,b=2,n=2 a=1,b=2,n=2,经while
条件再次运行至yield b
,返回b
值并暂停,打印m
,为2
; - 第4次
for
循环,接着a, b = b, a + b
向下运行,得到 a = 2 , b = 3 , n = 3 a=2,b=3,n=3 a=2,b=3,n=3,经while
条件再次运行至yield b
,返回b
值并暂停,打印m
,为3
; - 第5次
for
循环,接着a, b = b, a + b
向下运行,得到 a = 3 , b = 5 , n = 4 a=3,b=5,n=4 a=3,b=5,n=4,经while
条件再次运行至yield b
,返回b
值并暂停,打印m
,为5
; - 第6次
for
循环,接着a, b = b, a + b
向下运行,得到 a = 5 , b = 8 , n = 5 a=5,b=8,n=5 a=5,b=8,n=5,不满足while
条件,终止。
从上述拆解步骤,可以看出,若yield
语句不与while
循环体共同使用,yield
则只能起到一次暂停作用,就无法起到类似迭代器的作用。