Python 中 yield 关键字起什么作用?

要理解yield的作用,我们首先需要理解 可迭代对象(iterable)迭代器(iterator) 的概念。千万不要混淆可迭代对象、迭代器和生成器!

可迭代对象与迭代器

创建一个列表后,我们可以逐个读取它的元素,这个过程称为迭代

1
2
3
4
5
6
>>> a = [0, 1, 2]
>>> for i in a:
... print(i)
0
1
2

所有可以用于 for...in... 循环的对象,都是可迭代对象,比如列表、字符串、文件等。这些对象内部实现了 __iter__() 方法。

然而,可迭代对象通常会把所有元素一次性加载进内存。当数据量很大时,这可能会带来性能问题。

什么是生成器?

生成器(Generator)是一种特殊的迭代器,它不会一次性生成所有元素,而是在需要时动态生成值。生成器是“惰性”的,占用内存更少。

将列表推导式的方括号 [] 换成圆括号 (),就能得到一个生成器:

1
2
3
4
5
6
7
>>> a = [i for i in range(3)]
>>> type(a)
<class 'list'>

>>> b = (i for i in range(3))
>>> type(b)
<class 'generator'>

yield:创建生成器的关键字

使用 yield 可以将普通函数变成一个生成器函数。每次执行到 yield,函数会返回一个值,并暂停执行,保留当前状态。下一次调用 next() 时,会从上一次暂停的地方继续执行。

来看一个简单示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> def create_generator():
... mylist = range(3)
... for i in mylist:
... yield i * i

>>> mygenerator = create_generator()
>>> print(mygenerator)
<generator object create_generator at 0x...>

>>> for i in mygenerator:
... print(i)
0
1
4

你会发现,调用函数时并不会立即执行它,而是返回一个生成器对象。只有在遍历该生成器或调用 next() 时,函数才会逐步运行。

1
2
3
4
5
6
def some_function():
for i in range(4):
yield i

for i in some_function():
print(i)

和手动实现迭代器对比

不使用 yield,我们也可以手动实现一个迭代器类,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class MyIterator:
def __init__(self):
self.count = -1

def __iter__(self):
return self

def __next__(self):
self.count += 1
if self.count < 4:
return self.count
else:
raise StopIteration

def some_func():
return MyIterator()

for i in some_func():
print(i)

相比之下,使用 yield 可以让我们省去写 __iter____next__ 方法的麻烦,快速构建一个可迭代的对象。

总结

  • yield 是构建生成器的关键字。
  • 生成器通过 yield 动态生成值,具有惰性、节省内存的特点。
  • 相比手动实现迭代器,yield 提供了一种更简单、直观的方式。

当你想逐步生成数据,或者处理大量数据时,优先考虑使用生成器和 yield,它们会让你的代码更高效、更优雅。


Python 中 yield 关键字起什么作用?
https://vegetablest.github.io/2025/06/03/python-yield/
作者
af su
发布于
2025年6月3日
许可协议