Python - 生成器:初学者温和入门指南
你好,有抱负的Python程序员!今天,我们将开始一段激动人心的旅程,深入了解Python生成器的世界。如果你之前从未听说过生成器,不用担心——我们将从头开始,逐步深入学习。在本教程结束时,你将能够像专业人士一样创建生成器!
Python生成器是什么?
想象你正在阅读一本非常长的书。你不会一次性复印整本书(那样会浪费很多纸!),而是选择一次阅读一页。生成器在Python中的工作方式有点像这样!
生成器是一种特殊的函数,它允许我们随时间生成一系列值,而不是一次性计算所有值并将它们存储在内存中。它们就像魔法工厂,按需生成值。
为什么使用生成器?
- 内存效率:生成器对内存友好。它们不会一次性存储所有值在内存中。
- 性能:它们可以提升代码的性能,尤其是在处理大型数据集时。
- 简洁:生成器可以使你的代码更清晰、更易读。
让我们深入了解它们是如何工作的!
创建生成器
在Python中创建生成器主要有两种方法:
- 使用生成器函数
- 使用生成器表达式
生成器函数
生成器函数看起来就像一个普通函数,但使用的是yield
关键字,而不是return
。以下是一个简单示例:
def count_up_to(n):
i = 1
while i <= n:
yield i
i += 1
# 使用我们的生成器
for number in count_up_to(5):
print(number)
输出:
1
2
3
4
5
在这个例子中,count_up_to
是一个生成器函数。每次它产生一个值时,它都会暂停执行并记住其状态。下次调用时,它会从上次离开的地方继续。
生成器表达式
生成器表达式就像列表推导式,但使用圆括号而不是方括号。它们是一种紧凑的创建生成器的方式。以下是一个示例:
# 生成器表达式
squares = (x**2 for x in range(5))
# 使用我们的生成器
for square in squares:
print(square)
输出:
0
1
4
9
16
这个生成器表达式动态创建一个平方数的序列,而不会一次性将它们全部存储在内存中。
生成器中的异常处理
生成器也可以处理异常,这非常酷!以下是一个示例:
def div_generator(a, b):
try:
result = a / b
yield result
except ZeroDivisionError:
yield "不能除以零!"
# 使用我们的生成器
g = div_generator(10, 2)
print(next(g)) # 输出:5.0
g = div_generator(10, 0)
print(next(g)) # 输出:不能除以零!
在这个例子中,我们的生成器优雅地处理了尝试除以零的情况。
普通函数与生成器函数
让我们比较一个普通函数和一个生成器函数,看看区别:
# 普通函数
def get_squares(n):
squares = []
for i in range(n):
squares.append(i**2)
return squares
# 生成器函数
def gen_squares(n):
for i in range(n):
yield i**2
# 使用普通函数
print(get_squares(5)) # 输出:[0, 1, 4, 9, 16]
# 使用生成器函数
for square in gen_squares(5):
print(square) # 每个平方数在新的一行打印
主要区别在于:
- 内存使用:普通函数一次性创建并存储所有值,而生成器一次产生一个值。
- 语法:普通函数使用
return
,而生成器使用yield
。 - 迭代:生成器可以直接迭代,而普通函数的结果需要先存储在变量中。
异步生成器
Python 3.6引入了异步生成器,它们就像常规生成器,但是用于异步编程。它们使用async def
和yield
:
import asyncio
async def async_gen():
for i in range(3):
await asyncio.sleep(1)
yield i
async def main():
async for item in async_gen():
print(item)
asyncio.run(main())
这个例子模拟了一个异步操作,随时间产生值。
生成器方法
生成器有一些特殊的 方法,它们可能非常有用。以下是最常见的一些方法:
方法 | 描述 |
---|---|
next() |
从生成器中检索下一个项目 |
send() |
向生成器发送一个值 |
throw() |
在生成器内部抛出异常 |
close() |
关闭生成器 |
以下是一个使用send()
的快速示例:
def echo_generator():
while True:
received = yield
print(f"接收到的:{received}")
g = echo_generator()
next(g) # 初始化生成器
g.send("你好") # 输出:接收到的:你好
g.send("世界") # 输出:接收到的:世界
就这样!你已经迈出了进入神奇的Python生成器世界的第一步。记住,熟能生巧,所以不要害怕尝试这些概念。在你意识到之前,你将使用生成器来解决Python程序中的各种有趣问题。祝你编程愉快!
Credits: Image by storyset