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

 更新时间:2022年12月28日 09:04:47   作者:刘悦的技术博客  
这篇文章主要为大家介绍了Python3.10 Generator生成器Coroutine原生协程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

普遍意义上讲,生成器是一种特殊的迭代器,它可以在执行过程中暂停并在恢复执行时保留它的状态。而协程,则可以让一个函数在执行过程中暂停并在恢复执行时保留它的状态,在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'>

结语

诚然,生成器和协程也并非完全是一个概念,与生成器不同的是,协程可以被另一个函数(称为调用方)恢复执行,而不是只能由生成器本身恢复执行。这使得协程可以用来实现更复杂的控制流,因为它们可以在执行时暂停并在任意时刻恢复执行。

以上就是Python3.10 Generator生成器Coroutine原生协程详解的详细内容,更多关于Python生成器原生协程的资料请关注脚本之家其它相关文章!

相关文章

  • Python:__eq__和__str__函数的使用示例

    Python:__eq__和__str__函数的使用示例

    这篇文章主要介绍了Python:__eq__和__str__函数的使用示例,帮助大家更好的理解和学习python,感兴趣的朋友可以了解下
    2020-09-09
  • 零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers

    零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers

    文章首先介绍了urllib2的2个方法,然后详细介绍了urllib2中的2个重要概念Openers和Handlers的相关知识,希望能对大家有所帮助
    2014-11-11
  • 详解Python中静态类型语言的写法

    详解Python中静态类型语言的写法

    众所周知,python是一种动态类型语言,但是,从v3.6版本开始,开始支持静态类型的写法,下面小编就来和大家聊聊Python中静态类型语言的具体写法吧
    2023-07-07
  • Python数据类型及常用方法

    Python数据类型及常用方法

    这篇文章主要介绍了Python数据类型及常用方法 ,文章主要给大家分享Python的一些常用数据类型,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-04-04
  • Python Django模板之模板过滤器与自定义模板过滤器示例

    Python Django模板之模板过滤器与自定义模板过滤器示例

    这篇文章主要介绍了Python Django模板之模板过滤器与自定义模板过滤器,结合实例形式分析了Django框架模板过滤器与自定义模板过滤器相关功能、原理、使用方法及相关操作注意事项,需要的朋友可以参考下
    2019-10-10
  • Python使用pynlpir进行中文分词并保留段落信息

    Python使用pynlpir进行中文分词并保留段落信息

    nlpir是由张华平博士开发的中文自然处理工具,可以对中文文本进行分词、聚类分析等,本文主要介绍了使用pynlpir进行中文分词并保留段落信息的具体方法,希望对大家有所帮助
    2024-03-03
  • python抓取百度首页的方法

    python抓取百度首页的方法

    这篇文章主要介绍了python抓取百度首页的方法,涉及Python使用urllib模块实现页面抓取的相关技巧,需要的朋友可以参考下
    2015-05-05
  • Python中时间datetime的处理与转换用法总结

    Python中时间datetime的处理与转换用法总结

    今天小编就为大家分享一篇关于Python中时间datetime的处理与转换用法总结,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-02-02
  • python使用xlrd模块读取excel的方法实例

    python使用xlrd模块读取excel的方法实例

    Python读取Excel表格,相比xlwt来说,xlrd提供的接口比较多,下面这篇文章主要给大家介绍了关于python使用xlrd模块读取excel的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • 简单谈谈Python中的json与pickle

    简单谈谈Python中的json与pickle

    下面小编就为大家带来一篇简单谈谈Python中的json与pickle。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07

最新评论