跳转至

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 很像,都是用于函数的返回。但是 yieldreturn 不同的是,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 语句
如果再次执行函数,则从开头开始执行 从上一次暂停的地方开始执行