【Python 进阶】yield 关键词
💡简介
🖼️背景
- 当我们需要用到一组数据时,一种简单的方案是把它们全部提前生成/读入,保存在列表变量,存储在内存中。
- 这种方案的一个明显缺点是:内存占用过大。
- 在日常使用中可能不会造成什么明显后果,但当涉及的数据过多时就会对性能产生很大影响。
- 尤其是面对未知大小的文件,直接读入会导致不可预测的内存占用。
案例——生成斐波那契数列
1 | # 简单方案 |
🧠解决思路:延迟生成
- 数据之间可能存在一些逻辑关系,例如:
- 斐波那契数列中,前两个数产生第三个数
- 文件读取时,前一行数据的下一个位置是后一行数据的开头
- 我们可以用记录数据之间的逻辑关系来代替记录具体数据,更进一步地,仅当需要时才通过之前的数据及逻辑关系获得所需数据,也就是将数据的生成/读入过程延迟到数据被需要的时候。
🔨解决方案 1️⃣:迭代器
- 将上文中
fibonacci
函数改造为一个使用迭代器的类,迭代器不断生成下一个数。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# 迭代器方案
class Fibonacci:
def __init__(self, max):
self.max = max
self.n, self.a, self.b = 0, 0, 1
def __iter__(self):
return self
def __next__(self):
if self.n < self.max:
r = self.b
self.a, self.b = self.b, self.a + self.b
self.n = self.n + 1
return r
raise StopIteration()
for x in Fibonacci(1000):
print(x) - 很显然,这种方案带来的一个问题是复杂的代码格式,需要多写很多配置,不够优雅。
🔨解决方案 2️⃣:yield
- 使用 yield 关键字,可以很优雅地使函数成为一个生成器 generator。
- 看起来
fibonacci
函数仍然是个普通函数,但其返回值实际上是一个迭代器。(非常优雅)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# yield方案
def fibonacci(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
for x in fibonacci(1000):
print(x)
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成
while True:
try:
print(next(f), end=" ")
except StopIteration:
sys.exit()
💡原理
- 根据直观理解,yield 关键词和 return 关键词类似,能够返回一个东西。猜测可能是解释器看到 yield 时返回一个迭代器,并将相关代码赋给该迭代器。
- 感兴趣的小伙伴可以根据相关资料[3]理解一下底层原理。
- 希望这篇博客对你有帮助!如果你有任何问题或需要进一步的帮助,请随时提问。
- 如果你喜欢这篇文章,欢迎动动小手给我一个follow或star。
🗺参考文献
- 标题: 【Python 进阶】yield 关键词
- 作者: Fre5h1nd
- 创建于 : 2023-09-13 14:10:13
- 更新于 : 2023-12-08 20:31:54
- 链接: https://freshwlnd.github.io/2023/09/13/program_language/python/py-yield/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论