Python中yield关键字的使用详解

Python中yield关键字的使用详解

技术背景

在Python编程中,yield 关键字是一个非常强大且独特的特性。要理解 yield 的作用,需要先了解可迭代对象(iterables)、迭代器(iterators)和生成器(generators)的概念。可迭代对象是指可以使用 for... in... 语句进行遍历的对象,如列表、字符串、文件等。迭代器是实现了 __next__() 方法的对象,它允许我们逐个访问可迭代对象中的元素。而生成器是一种特殊的迭代器,它可以在需要时生成值,而不是一次性将所有值存储在内存中,这在处理大量数据时非常有用。

实现步骤

可迭代对象

当创建一个列表时,可以逐个读取其元素,这种操作称为迭代。例如:

1
2
3
mylist = [1, 2, 3]
for i in mylist:
print(i)
PYTHON

使用列表推导式创建的列表也是可迭代对象:

1
2
3
mylist = [x*x for x in range(3)]
for i in mylist:
print(i)
PYTHON

生成器

生成器是一种特殊的迭代器,只能迭代一次,它不会将所有值存储在内存中,而是在需要时生成值。可以使用生成器表达式创建生成器:

1
2
3
mygenerator = (x*x for x in range(3))
for i in mygenerator:
print(i)
PYTHON

需要注意的是,生成器只能使用一次,再次迭代将不会有任何输出。

yield关键字

yield 是一个关键字,用于定义生成器函数。当函数中包含 yield 关键字时,该函数将返回一个生成器对象。例如:

1
2
3
4
5
6
7
8
def create_generator():
mylist = range(3)
for i in mylist:
yield i*i

mygenerator = create_generator()
for i in mygenerator:
print(i)
PYTHON

核心代码

简单生成器函数示例

1
2
3
4
5
6
7
8
9
def makeRange(n):
i = 0
while i < n:
yield i
i += 1

gen = makeRange(5)
for num in gen:
print(num)
PYTHON

协程示例

1
2
3
4
5
6
7
8
9
10
11
12
def bank_account(deposited, interest_rate):
while True:
calculated_interest = interest_rate * deposited
received = yield calculated_interest
if received:
deposited += received

my_account = bank_account(1000, .05)
first_year_interest = next(my_account)
print(first_year_interest)
next_year_interest = my_account.send(first_year_interest + 1000)
print(next_year_interest)
PYTHON

最佳实践

处理大量数据

当需要处理大量数据时,使用生成器可以避免将所有数据存储在内存中,从而节省内存。例如,处理大文件时,可以逐行读取文件内容:

1
2
3
4
5
6
7
8
9
def read_file(file_path):
with open(file_path, 'r') as file:
for line in file:
yield line

file_gen = read_file('large_file.txt')
for line in file_gen:
# 处理每一行数据
pass
PYTHON

实现无限序列

生成器可以用于实现无限序列,如斐波那契数列:

1
2
3
4
5
6
7
8
9
def fib():
last, cur = 0, 1
while True:
yield cur
last, cur = cur, last + cur

fib_gen = fib()
for i in range(10):
print(next(fib_gen))
PYTHON

常见问题

生成器只能使用一次

生成器是一次性使用的迭代器,一旦耗尽,就不能再次使用。如果需要多次使用生成器的结果,可以将其转换为列表:

1
2
3
4
gen = makeRange(5)
result_list = list(gen)
for num in result_list:
print(num)
PYTHON

混淆可迭代对象、迭代器和生成器

可迭代对象是可以使用 for... in... 语句遍历的对象,迭代器是实现了 __next__() 方法的对象,而生成器是一种特殊的迭代器。需要注意它们之间的区别,避免混淆。

在生成器表达式或列表推导式中使用 yield

CPython 核心开发者正在讨论弃用在生成器表达式或列表推导式中使用 yield 的语法,因此不建议在这些场景中使用 yield


Python中yield关键字的使用详解
https://119291.xyz/posts/python-yield-keyword-explanation/
作者
ww
发布于
2025年5月6日
许可协议