Python 语言进阶 —— yield表达式
介绍
在 Python 的 官网 中,对 yield 表达式的解释如下:
yield 表达式在定义 generator 函数或 asynchronous generator 函数时才会用到因此只能在函数定义的内部使用。 在一个函数体内使用 yield 表达式会使这个函数变成一个生成器函数,而在一个 async def 函数的内部使用它则会让这个协程函数变成一个异步生成器函数。
简单而言就是:在函数中添加 yield
关键字会使该函数返回一个生成器对象,该对象可以被迭代。
def simple():
x = 1
yield x
yield x + 1
yield x + 2
s = simple()
print(s)
输出的是一个迭代器对象:
<generator object simple at 0x0000022568E34B80>
迭代器对象
yield
的作用和 return
很像,都是用于函数的返回。但是 yield
与 return
不同的是,return
返回的是某个值,在返回时会清空函数产生的临时变量。
而 yield
返回的是一个可以迭代的生成器。当获取到 yield
返回的对象时,可以通过 for 循环或者是 next()
函数进行迭代。
因为是一个迭代器对象,就可以通过迭代的方式读取其中的值:
def simple():
x = 1
yield x
yield x + 1
yield x + 2
if __name__ == '__main__':
s = simple()
for i in s:
print(i)
输出:
1
2
3
也可以使用 next()
函数进行迭代:
def simple():
x = 1
yield x
yield x + 1
yield x + 2
if __name__ == '__main__':
s = simple()
print(next(s))
print(next(s))
print(next(s))
print(next(s)) # 这里会报错,因为此处已经不可迭代。
运行可以得到相同的结果。因为在 simple() 函数中只 yield
了三次,因此当进行第 4 次迭代的时候会报错:
1
2
3
Traceback (most recent call last):
File "D:\Projects\Python\PythonDemos\yielddemo.py", line 13, in <module>
print(next(s))
^^^^^^^
StopIteration
不清理局部变量
yield
的返回不会像 return
一样清理函数中局部变量。更准确地说,应该是 yield
会阻止函数退出,直到下次调用 next()
方法。当调用时,将从之前暂停的位置继续开始执行。
def simple():
num = 1
print("First time execution of the function")
yield num # 第 1 次调用在此处停止,不清理局部变量 num 的值
num = 10
print("Second time execution of the function")
yield num # 第 2 次调用在此处停止,不清理局部变量 num 的值
num = 100
print("Third time execution of the function")
yield num # 第 3 次调用在此处停止,不清理局部变量 num 的值
if __name__ == '__main__':
s = simple()
print('--- First time start ---')
print(next(s))
print('--- First time end ---\n')
print('--- Second time start ---')
print(next(s))
print('--- Second time end ---\n')
print('--- Third time start ---')
print(next(s))
print('--- Third time end ---\n')
执行上述代码,输出如下:
--- First time start ---
First time execution of the function
1
--- First time end ---
--- Second time start ---
Second time execution of the function
10
--- Second time end ---
--- Third time start ---
Third time execution of the function
100
--- Third time end ---
与 return 的关系
Return | Yield |
---|---|
将结果返回给调用者(函数外部) | 用于将函数转换为生成器。暂停函数执行并保留其状态 |
执行完毕后销毁变量(局部变量生命周期结束) | yield 不会销毁函数的局部变量。它会保留状态。 |
通常每个函数只有一个 return 语句 |
可以有一个或多个 yield 语句 |
如果再次执行函数,则从开头开始执行 | 从上一次暂停的地方开始执行 |