Python - 生成器


Python 中的生成器是一种特殊类型的函数,它返回迭代器对象。它看起来与普通的 Python 函数类似,它的定义也以 def 关键字开头。然而,生成器使用了yield 关键字,而不是最后的return 语句。

句法

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

函数末尾的return语句表示函数体执行结束,函数内所有局部变量退出作用域。如果再次调用该函数,局部变量将重新初始化。

生成器函数的Behave有所不同。它像普通函数一样第一次被调用,但是当它的yield语句到来时,它的执行会暂时暂停,将控制权转移回来。产生的结果由调用者使用。对 next() 内置函数的调用将从暂停点重新开始执行生成器,并为迭代器生成下一个对象。当随后的yield 提供迭代器中的下一个项目(它已耗尽)时,循环会重复。

实施例1

下面代码中的函数是一个生成器,它连续生成从 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 序列对象获取的普通迭代器具有更高的内存效率。例如,如果您想获取斐波那契数列的前 n 个数字。您可以编写一个普通函数并构建一个斐波那契数列表,然后使用循环迭代该列表。

实施例2

下面给出的是获取斐波那契数列表的正常函数 -

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

上面的代码将所有斐波那契数列收集到一个列表中,然后使用循环遍历该列表。想象一下,我们希望斐波那契数列达到一个很大的数字。在这种情况下,所有数字必须收集在一个需要大量内存的列表中。这就是生成器有用的地方,因为它在列表中生成单个数字并提供它以供使用。

实施例3

以下代码是斐波那契数列表的基于生成器的解决方案 -

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 

异步发电机

异步生成器是返回异步迭代器的协程。协程是使用 async 关键字定义的 Python 函数,它可以调度和等待其他协程和任务。就像普通的生成器一样,异步生成器在每次调用ext()函数而不是next()函数时都会在迭代器中生成增量项。

句法

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

实施例4

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

实施例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