Python - 生成器



Python 生成器

Python 中的生成器是创建迭代器的一种便捷方式。它们允许我们迭代一系列值,这意味着值是动态生成的,而不是存储在内存中,这对于大型数据集或无限序列特别有用。

Python 中的生成器是一种特殊的函数,它返回一个迭代器对象。它看起来类似于普通的 Python 函数,其定义也以 def 关键字开头。但是,它不像普通函数那样在结尾使用 return 语句,而是使用 yield 关键字。

语法

以下是 **generator()** 函数的语法:

def generator():
 . . .
 . . .
 yield obj
it = generator()
next(it)
. . .

创建生成器

在 Python 中创建生成器主要有两种方法:

  • 使用生成器函数
  • 使用生成器表达式

使用生成器函数

生成器函数使用 '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

使用生成器表达式

生成器表达式提供了一种简洁的创建生成器的方法。它们使用类似于列表推导式的语法,但使用圆括号 () 而不是方括号 []。

gen_expr = (x * x for x in range(1, 6))

for value in gen_expr:
    print(value)

输出

1
4
9
16
25

生成器中的异常处理

我们可以创建一个生成器,并使用带有 'StopIteration' 异常处理的 'while' 循环来迭代它。下面代码中的函数是一个生成器,它连续地产生从 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

输出

1
2
3
4
5

普通函数与生成器函数

Python 中的普通函数和生成器函数服务于不同的目的,并表现出不同的行为。理解它们的区别对于有效地利用它们至关重要。

普通函数在被调用时计算并返回单个值或一组值(在列表或元组中)。一旦返回,函数的执行就完成了,所有局部变量都被丢弃;而生成器函数每次产生一个值,并在每次 yield 之间暂停和恢复其状态。它使用 yield 语句而不是 return 语句。

示例

在这个例子中,我们创建一个普通函数,构建一个斐波那契数列的列表,然后使用循环迭代该列表:

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)

输出

1
2
3
5
8

示例

在上面的例子中,我们使用普通函数创建了斐波那契数列。当我们想将所有斐波那契数列的数字收集到一个列表中,然后使用循环遍历该列表时。想象一下,如果我们想要一个很大的斐波那契数列。

在这种情况下,所有数字都必须收集到一个列表中,这需要大量的内存。这就是生成器有用的地方,因为它一次生成列表中的一个数字并提供使用。以下代码是基于生成器的斐波那契数列解决方案:

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

异步生成器

异步生成器是一个返回异步迭代器的协程。协程是一个用async关键字定义的Python函数,它可以调度和等待其他协程和任务。

就像普通的生成器一样,异步生成器在每次调用anext()函数(而不是next()函数)时都会在迭代器中产生增量项。

语法

以下是异步生成器的语法:

async def generator():
. . .
. . .
yield obj
it = generator()
anext(it)
. . .

示例

以下代码演示了一个协程生成器,它在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())

输出

1
2
3
4
5

示例

现在让我们为斐波那契数列编写一个异步生成器。为了模拟协程内部的一些异步任务,程序在产生下一个数字之前调用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())

输出

1
2
3
5
8
广告