Python generators, coroutines, native coroutines and async/await

Python generators, coroutines, native coroutines and async/await
最新回答
小草泠泠

2026-10-22 23:48:17

Python中的生成器、协程、原生协程和async/await是异步编程中的关键概念,以下是对这些概念的详细解释和代码示例:

  • 生成器(Generators)

生成器是一种特殊的函数,用于生成一系列值。与普通函数不同,生成器使用yield关键字来暂停执行并返回一个值,而不是使用return。当再次调用生成器时,它会从上次暂停的地方继续执行。

def simple_gen(): yield 'hello' yield 'world'gen = simple_gen()print(type(gen)) # <class 'generator'>print(next(gen)) # 'hello'print(next(gen)) # 'world'

生成器常用于节省内存,特别是当需要处理大量数据时。例如,可以使用生成器来逐个生成值,而不是一次性生成整个列表。

def f(n): res = [] for i in range(n): res.append(i) return resdef yield_n(n): for i in range(n): yield i
  • 协程(Coroutines)

协程是一种特殊的生成器,它不仅可以生成值,还可以接收外部发送的数据。协程使用yield作为表达式,允许通过send()方法向协程内部发送数据。

def coro(): hello = yield 'hello' # yield作为表达式,可以接收send的值 yield helloc = coro()print(next(c)) # 输出 'hello'print(c.send('world')) # 输出 'world'

在协程中,next()或send(None)用于启动协程,之后可以使用send()方法发送数据并恢复协程的执行。

  • 原生协程与async/await

Python 3.5引入了async和await关键字,用于定义原生协程。原生协程提供了更简洁的语法,并且与基于生成器的协程在功能上没有区别,但不能混用。

import asyncioasync def my_coroutine(): await asyncio.sleep(1) print("Coroutine executed")loop = asyncio.get_event_loop()loop.run_until_complete(my_coroutine())loop.close()

原生协程使用async def定义,内部使用await来等待其他协程或异步操作完成。

  • 异步I/O和asyncio模块

asyncio模块是Python标准库中用于异步编程的框架。它提供了事件循环、协程、任务等功能,使得异步编程更加简洁和高效。

import asyncioasync def display_date(num, loop): end_time = loop.time() + 5.0 while True: print("Loop: {} Time: {}".format(num, loop.time())) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(1)loop = asyncio.get_event_loop()asyncio.ensure_future(display_date(1, loop))asyncio.ensure_future(display_date(2, loop))loop.run_forever()

在这个例子中,两个协程并发执行,通过asyncio.sleep()模拟异步I/O操作。事件循环负责调度协程的执行,使得它们能够高效地利用系统资源。

  • 原生协程与基于生成器的协程的互操作性

虽然原生协程和基于生成器的协程在语法上有所不同,但它们在功能上是相似的,并且可以在一定程度上互操作。例如,可以在原生协程中await一个基于生成器的协程,或者反之。

import asyncioimport types@types.coroutinedef my_sleep_func(): yield from asyncio.sleep(1)async def my_coroutine(): await my_sleep_func() print("Coroutine executed")loop = asyncio.get_event_loop()loop.run_until_complete(my_coroutine())loop.close()

在这个例子中,my_sleep_func是一个基于生成器的协程,而my_coroutine是一个原生协程。通过@types.coroutine装饰器,使得基于生成器的协程可以在原生协程中被await。