Python 简明教程
Python - Generators
Python Generators
Python 中的生成器是创建迭代器的便捷方式。它们允许我们对值序列进行迭代,这意味着值是动态生成的,而不是存储在内存中,这对于大型数据集或无限序列尤其有用。
Python 中的生成器是一种返回迭代器对象的特殊函数类型。它看上去类似于普通 Python 函数,其定义也以 def 关键字开头。但是,生成器在结尾处使用 yield 关键字,而不是使用 return 语句。
Creating Generators
在 python 中主要有两种创建生成器的方法 -
-
Using Generator Functions
-
Using Generator Expressions
Using Generator Functions
生成器函数使用 'yield' 语句一次性返回所有值。每次调用生成器的 next() 方法时,生成器会从上次 yield 语句之后的点继续执行。下面是创建生成器函数的示例。
def count_up_to(max_value):
current = 1
while current <= max_value:
yield current
current += 1
# Using the generator
counter = count_up_to(5)
for number in counter:
print(number)
1
2
3
4
5
Exception Handling in Generators
我们可以使用带有异常处理的 'while' 循环创建生成器并对其进行遍历,以应对 'StopIteration' 异常。以下代码中的函数是一个生成器,可连续产生 1 到 5 的整数。
调用此函数时,它会返回一个迭代器。每次调用 next() 方法都会将控制权转移回生成器并获取下一个整数。
def generator(num):
for x in range(1, num+1):
yield x
return
it = generator(5)
while True:
try:
print (next(it))
except StopIteration:
break
Normal function vs Generator function
Python 中的普通函数和生成器函数具有不同的用途,并表现出不同的行为。了解它们之间的差异对于有效地在我们的代码中利用它们至关重要。
普通函数在被调用时计算并返回一个值或一组值,无论是在列表还是元组中。一旦返回,函数将执行完毕,所有局部变量都会被丢弃,而生成器函数会通过在每次 yield 之间暂停并恢复其状态来一次生成一个值。它使用 yield 语句,而不是 return 语句。
Example
在本例中,我们创建一个普通函数并构建一个 Fibonacci 数列表,然后使用循环遍历该列表 -
def fibonacci(n):
fibo = []
a, b = 0, 1
while True:
c=a+b
if c>=n:
break
fibo.append(c)
a, b = b, c
return fibo
f = fibonacci(10)
for i in f:
print (i)
Example
在上面的示例中,我们使用普通函数创建了一个 Fibonacci 数列。当我们要将所有 Fibonacci 数列数字收集到一个列表中时,再使用循环遍历该列表。假设我们希望 Fibonacci 数列达到一个大数。
在这样的情况下,必须将所有数字收集到一个列表中,这需要占用大量的内存。这就是生成器发挥作用的地方,因为它在列表中生成一个数字并将其提供供使用。以下代码是基于生成器的 Fibonacci 数列解决方案 -
def fibonacci(n):
a, b = 0, 1
while True:
c=a+b
if c>=n:
break
yield c
a, b = b, c
return
f = fibonacci(10)
while True:
try:
print (next(f))
except StopIteration:
break
输出
1
2
3
5
8
Asynchronous Generator
异步生成器是一个返回异步迭代器的协程。协程是由 async 关键字定义的 Python 函数,它可以调度并等待其他协程和任务。
与普通生成器一样,异步生成器在每次调用 anext() 函数时(而不是 next() 函数)在迭代器中生成增量项。
Example
以下代码演示了一个协程生成器,该生成器在 async for 循环的每次迭代中生成递增的整数。
import asyncio
async def async_generator(x):
for i in range(1, x+1):
await asyncio.sleep(1)
yield i
async def main():
async for item in async_generator(5):
print(item)
asyncio.run(main())
Example
现在,让我们编写一个 Fibonacci 数的异步生成器。为了在协程内部模拟一些异步任务,程序会在生成下一个数字之前调用 sleep() 方法,持续 1 秒钟。因此,在延迟一秒钟后,我们将在屏幕上看到数字被打印出来。
import asyncio
async def fibonacci(n):
a, b = 0, 1
while True:
c=a+b
if c>=n:
break
await asyncio.sleep(1)
yield c
a, b = b, c
return
async def main():
f = fibonacci(10)
async for num in f:
print (num)
asyncio.run(main())