Python 生成器
在Python中,生成器是一种特殊类型的函数,它返回一个迭代器对象。它看起来类似于普通的Python函数,因为它的定义也以def关键字开头。然而,不同于在最后使用return语句,生成器使用yield关键字。
语法
def generator():
. . .
. . .
yield obj
it = generator()
next(it)
. . .
return语句在函数末尾表示函数体的执行结束,所有函数中的局部变量都超出了作用域。如果再次调用函数,则会重新初始化局部变量。
生成器函数的行为不同。它首次被调用时像普通函数一样执行,但当遇到yield语句时,它的执行被暂时暂停,并将控制权返回。产生的结果由调用者消费。调用next()内置函数会从暂停的位置重新开始执行生成器,并生成迭代器的下一个对象。随后的yield会提供迭代器中的下一个项,直到迭代器被耗尽为止。
示例1
下面的代码中的函数是一个生成器,通过yield连续生成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中定义的函数,它可以调度和等待其他协程和任务。与普通生成器一样,异步生成器在每次调用anext()函数而不是next()函数时,在迭代器中逐步生成项目。
语法
async def generator():
. . .
. . .
yield obj
it = generator()
anext(it)
. . .
示例4
下面的代码演示了一个协程生成器,在每次迭代循环时,生成递增的整数。
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