Python3.10 Generator生成器Coroutine原生协程详解

作者:刘悦的技术博客 时间:2023-10-25 15:31:36 

引言

普遍意义上讲,生成器是一种特殊的迭代器,它可以在执行过程中暂停并在恢复执行时保留它的状态。而协程,则可以让一个函数在执行过程中暂停并在恢复执行时保留它的状态,在Python3.10中,原生协程的实现手段,就是生成器,或者说的更具体一些:协程就是一种特殊的生成器,而生成器,就是协程的入门心法。

协程底层实现

我们知道,Python3.10中可以使用async和await关键字来实现原生协程函数的定义和调度,但其实,我们也可以利用生成器达到协程的效果,生成器函数和普通函数的区别在于,生成器函数使用 yield 语句来暂停执行并返回结果。例如,下面是一个使用生成器函数实现的简单协程:

def my_coroutine():  
   while True:  
       x = yield  
       print(x)  
# 使用生成器函数创建协程  
coroutine = my_coroutine()  
# 启动协程  
next(coroutine)  
# 在协程中传入数据  
coroutine.send(1)  
coroutine.send(2)  
coroutine.send(3)

程序返回:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/test.py"  
1  
2  
3

在上面的代码中,生成器函数 my_coroutine 使用了一个无限循环来实现协程的逻辑。每当调用 send 方法时,协程就会从 yield 语句处恢复执行,并将传入的参数赋值给变量 x。

如此,就完成了协程执行-》阻塞-》切换-》回调的工作流模式。

当然,作为事件循环机制,协程服务启动可能无限期地运行,要关闭协程服务,可以使用生成器的close()方法。当一个协程被关闭时,它会生成GeneratorExit异常,该异常可以用生成器的方式进行捕获:

def my_coroutine():  
   try :  
       while True:  
           x = yield  
           print(x)  
   except GeneratorExit:  
           print("协程关闭")  
# 使用生成器函数创建协程  
coroutine = my_coroutine()  
# 启动协程  
next(coroutine)  
# 在协程中传入数据  
coroutine.send(1)  
coroutine.send(2)  
coroutine.send(3)  
coroutine.close()

程序返回:

➜  mydemo git:(master) ✗ /opt/homebrew/bin/python3.10 "/Users/liuyue/wodfan/work/mydemo/src/test.py"  
1  
2  
3  
协程关闭

业务场景

在实际业务场景中,我们也可以使用生成器来模拟协程流程,主要体现在数据的IO流操作中,假设我们需要从本地往服务器传输数据,首先建立链接对象:

class Connection:  
   def __init__(self, addr):  
       self.addr = addr  
   def transmit(self, data):  
       print(f"X: {data[0]}, Y: {data[1]} sent to {self.addr}")

随后建立生成器函数:

def send_to_server(conn):  
   while True:  
       try:  
           raw_data = yield  
           raw_data = raw_data.split(' ')  
           coords = (float(raw_data[0]), float(raw_data[1]))  
           conn.transmit(coords)  
       except ConnectionError:  
           print("链接丢失,进行回调")  
           conn = Connection("重新连接v3u.cn")

利用生成器调用链接类的transmit方法进行数据的模拟传输,如果链接断开,则会触发回调重新连接,执行逻辑:

if __name__ == '__main__':  
   conn = Connection("v3u.cn")  
   sender = send_to_server(conn)  
   sender.send(None)  
   for i in range(1, 6):  
       sender.send(f"{100/i} {200/i}")  
   # 模拟链接断开  
   conn.addr = None  
   sender.throw(ConnectionError)  
   for i in range(1, 6):  
       sender.send(f"{100/i} {200/i}")

程序返回:

X: 100.0, Y: 200.0 sent to v3u.cn  
X: 50.0, Y: 100.0 sent to v3u.cn  
X: 33.333333333333336, Y: 66.66666666666667 sent to v3u.cn  
X: 25.0, Y: 50.0 sent to v3u.cn  
X: 20.0, Y: 40.0 sent to v3u.cn  
链接丢失,进行回调  
X: 100.0, Y: 200.0 sent to 重新连接v3u.cn  
X: 50.0, Y: 100.0 sent to 重新连接v3u.cn  
X: 33.333333333333336, Y: 66.66666666666667 sent to 重新连接v3u.cn  
X: 25.0, Y: 50.0 sent to 重新连接v3u.cn  
X: 20.0, Y: 40.0 sent to 重新连接v3u.cn

如此,我们就可以利用生成器的“状态保留”机制来控制网络链接突然断开的回调补救措施了。

所以说,协程就是一种特殊的生成器:

async def test():  
   pass  
print(type(test()))

您猜怎么着?

<class 'coroutine'>

来源:https://juejin.cn/post/7181766056719941690

标签:Python,Generator,Coroutine,生成器,原生协程
0
投稿

猜你喜欢

  • 实战手记:让百万级数据瞬间导入SQL Server

    2010-06-07 14:13:00
  • 如何获取浏览器的更多信息?

    2009-11-23 20:48:00
  • iis、apache与nginx禁止目录执行asp、php脚本的实现方法

    2023-10-14 11:30:26
  • 13个超级有用的 jQuery 内容滚动插件和教程

    2011-08-10 19:10:08
  • Python编解码问题及文本文件处理方法详解

    2021-04-13 07:52:06
  • 小xiao说说创意图标设计心得

    2009-11-18 12:27:00
  • Python 添加文件注释和函数注释操作

    2021-07-23 07:16:54
  • Vue父子传递实例讲解

    2023-07-02 17:03:29
  • SQL Server数据库查询优化3种技巧

    2008-10-17 10:10:00
  • 如何解决cmd运行python提示不是内部命令

    2022-02-05 05:05:38
  • ASP解析JSON

    2009-12-25 16:34:00
  • Python OpenCV基于HSV的颜色分割实现示例

    2021-11-04 19:24:26
  • Java连接数据库oracle中文乱码解决方案

    2024-01-19 02:48:10
  • python将pandas datarame保存为txt文件的实例

    2021-11-17 06:21:51
  • Python将视频或者动态图gif逐帧保存为图片的方法

    2022-08-08 00:50:17
  • python 图像判断,清晰度(明暗),彩色与黑白实例

    2023-09-04 12:58:00
  • 谷歌浏览器Chrome的javascript引擎

    2008-09-04 12:24:00
  • 用户研究角度看设计(1)“复制链接”的故事

    2008-12-26 17:48:00
  • 更新修改后的Python模块方法

    2022-02-20 15:34:09
  • Mysql常用基准测试命令总结

    2024-01-22 17:22:05
  • asp之家 网络编程 m.aspxhome.com