当前位置: 首页 > news >正文

【Python】理解Python中的协程和生成器:从yield到async

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门!

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界

在现代编程中,异步编程成为提升程序性能和响应速度的重要手段。Python作为一门功能强大的编程语言,提供了丰富的工具来实现异步操作,其中协程和生成器是核心概念。本文将深入探讨Python中协程和生成器的实现方式,从基础的yield语句入手,逐步引导读者理解生成器的工作机制,进而介绍如何将生成器转换为协程。通过详细的代码示例和中文注释,本文不仅阐明了协程与生成器的概念,还展示了它们在实际开发中的应用场景。此外,文章还将介绍Python 3.5引入的asyncawait关键字,解析其背后的原理与优势。无论是初学者还是有经验的开发者,本文都将帮助读者全面掌握Python中的协程与生成器,提升编程效率与代码质量。


目录

  1. 引言
  2. 生成器的基础
    • 什么是生成器
    • yield的使用
    • 生成器的优势
  3. 生成器的高级特性
    • 生成器的send方法
    • 生成器的throw方法
    • 生成器的close方法
  4. 协程的基础
    • 什么是协程
    • 协程与线程的区别
    • 协程的优点
  5. 从生成器到协程
    • 生成器作为协程的基础
    • 协程的调度与管理
  6. Python中的asyncawait
    • async的使用
    • await的使用
    • asyncawait的工作原理
  7. 异步编程的应用场景
    • I/O密集型任务
    • 高并发网络服务
    • 实时数据处理
  8. 实践案例
    • 使用生成器实现简单的协程
    • 使用asyncawait构建异步HTTP请求
    • 比较生成器协程与async协程的性能
  9. 常见问题与解决方案
  10. 结论
  11. 参考文献

引言

随着互联网和分布式系统的迅猛发展,应用程序需要处理大量的并发任务和高频率的I/O操作。传统的同步编程模型在面对这些需求时,往往表现出性能瓶颈,难以高效利用系统资源。为了应对这些挑战,异步编程应运而生,成为提升程序性能和响应速度的重要手段。

在Python中,生成器(Generator)和协程(Coroutine)是实现异步编程的两大关键概念。生成器通过yield语句实现延迟计算和数据流的生成,而协程则提供了一种更加灵活和高效的方式来管理并发任务。自Python 3.5引入asyncawait关键字以来,协程的使用变得更加便捷和强大。

本文旨在系统地介绍Python中的生成器与协程,深入解析它们的工作原理、实现方式以及在实际开发中的应用。通过详细的代码示例和丰富的中文注释,本文将帮助读者全面掌握协程与生成器的使用方法,提升编程效率与代码质量。

生成器的基础

什么是生成器

生成器(Generator)是Python中一种用于创建迭代器的简单而强大的工具。与普通函数不同,生成器使用yield语句返回数据,每次调用时会记住上一次的执行状态,从而能够逐步生成数据。这种特性使得生成器在处理大量数据或无限数据流时,表现出极高的效率和灵活性。

生成器的核心在于其能够暂停和恢复执行,这通过yield语句实现。当生成器函数执行到yield时,会将值返回给调用者,并冻结当前的执行状态,等待下一次调用继续执行。

yield的使用

yield是生成器的关键字,用于在函数内部返回一个值,并暂停函数的执行。每次调用生成器的__next__()方法时,函数会从上一次暂停的地方继续执行,直到遇到下一个yield语句或函数结束。

以下是一个简单的生成器示例:

# 定义一个生成器函数,生成斐波那契数列
def fibonacci(n):a, b = 0, 1for _ in range(n):yield aa, b = b, a + b# 创建生成器对象
fib = fibonacci(10)# 使用for循环遍历生成器
for num in fib:print(num)

输出:

0
1
1
2
3
5
8
13
21
34

在上述代码中,fibonacci函数是一个生成器函数,它使用yield语句逐步生成斐波那契数列。每次调用__next__()方法时,生成器会返回下一个斐波那契数。

生成器的优势

生成器相比于普通函数和列表推导式,具有以下几个显著优势:

  1. 内存效率高:生成器按需生成数据,不需要一次性将所有数据存储在内存中,适合处理大型数据集或无限数据流。
  2. 惰性求值:生成器在每次迭代时才生成下一个值,避免了不必要的计算,提高了程序的性能。
  3. 简洁的语法:使用yield语句,生成器代码更为简洁,易于理解和维护。
  4. 支持协作式多任务:生成器可以在执行过程中暂停,配合send等方法,实现协作式的多任务处理。

生成器的高级特性

在理解了生成器的基本用法后,进一步探讨其高级特性,可以更好地利用生成器的强大功能。

生成器的send方法

生成器不仅可以用来生成值,还可以接收外部传入的值。通过send方法,可以向生成器发送数据,并在生成器内部使用这些数据。

以下是一个使用send方法的示例:

# 定义一个生成器,接收外部发送的数据
def echo():while True:received = yieldprint(f"Received: {received}")# 创建生成器对象
generator = echo()# 启动生成器
next(generator)# 发送数据到生成器
generator.send("Hello")
generator.send("World")
generator.send(123)

输出:

Received: Hello
Received: World
Received: 123

在这个示例中,echo生成器在每次yield后等待接收数据,通过generator.send()方法将数据发送到生成器,并在生成器内部打印接收到的数据。

生成器的throw方法

throw方法允许向生成器抛出一个异常,这在生成器内部进行异常处理时非常有用。

以下是一个使用throw方法的示例:

# 定义一个生成器,处理异常
def divide():while True:try:x = yieldresult = 10 / xprint(f"10 / {x} = {result}")except ZeroDivisionError:print("除数不能为零!")# 创建生成器对象
gen = divide()# 启动生成器
next(gen)# 发送有效数据
gen.send(2)# 发送导致除零的值
gen.send(0)# 发送另一个有效数据
gen.send(5)

输出:

10 / 2 = 5.0
除数不能为零!
10 / 5 = 2.0

在上述代码中,divide生成器通过try-except块捕获ZeroDivisionError异常。当发送0作为除数时,生成器捕获到异常并打印错误信息,而不会导致程序崩溃。

生成器的close方法

close方法用于关闭生成器,导致生成器抛出一个GeneratorExit异常,从而终止生成器的执行。

以下是一个使用close方法的示例:

# 定义一个生成器,处理生成器关闭
def generator_example():try:

相关文章:

【Python】理解Python中的协程和生成器:从yield到async

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代编程中,异步编程成为提升程序性能和响应速度的重要手段。Python作为一门功能强大的编程语言,提供了丰富的工具来实现异步操作,其中…...

Unity开发游戏使用XLua的基础

Unity使用Xlua的常用编码方式,做一下记录 1、C#调用lua 1、Lua解析器 private LuaEnv env new LuaEnv();//保持它的唯一性void Start(){env.DoString("print(你好lua)");//env.DoString("require(Main)"); 默认在resources文件夹下面//帮助…...

什么是区块链

区块链是一种去中心化的分布式账本技术,它通过一系列复杂而精密的设计原则和机制来确保数据的安全性、透明性和不可篡改性。在最基础的层面上,区块链是由一系列按照时间顺序链接起来的数据块组成的链式结构。每个数据块中包含了一定数量的交易记录或状态…...

C++中的析构器(Destructor)(也称为析构函数)

在C中,析构器(Destructor)也称为析构函数,它是一种特殊的成员函数,用于在对象销毁时进行资源清理工作。以下是关于C析构器的详细介绍: 析构函数的特点 名称与类名相同,但前面有一个波浪号 ~&a…...

【ts + java】古玩系统开发总结

src别名的配置 开发中文件和文件的关系会比较复杂,我们需要给src文件夹一个别名吧 vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import path from path// https://vitejs.dev/config/ export default defineConfig({pl…...

NLP深度学习 DAY5:Sequence-to-sequence 模型详解

Seq2Seq(Sequence-to-Sequence)模型是一种用于处理输入和输出均为序列任务的深度学习模型。它最初被设计用于机器翻译,但后来广泛应用于其他任务,如文本摘要、对话系统、语音识别、问答系统等。 核心思想 Seq2Seq 模型的目标是将…...

音视频多媒体编解码器基础-codec

如果要从事编解码多媒体的工作,需要准备哪些更为基础的内容,这里帮你总结完。 因为数据类型不同所以编解码算法不同,分为图像、视频和音频三大类;因为流程不同,可以分为编码和解码两部分;因为编码器实现不…...

数据分析系列--⑦RapidMiner模型评价(基于泰坦尼克号案例含数据集)

一、前提 二、模型评估 1.改造⑥ 2.Cross Validation算子说明 2.1Cross Validation 的作用 2.1.1 模型评估 2.1.2 减少过拟合 2.1.3 数据利用 2.2 Cross Validation 的工作原理 2.2.1 数据分割 2.2.2 迭代训练与测试 ​​​​​​​ 2.2.3 结果汇总 ​​​​​​​ …...

【react+redux】 react使用redux相关内容

首先说一下,文章中所提及的内容都是我自己的个人理解,是我理逻辑的时候,自我说服的方式,如果有问题有补充欢迎在评论区指出。 一、场景描述 为什么在react里面要使用redux,我的理解是因为想要使组件之间的通信更便捷…...

nacos 配置管理、 配置热更新、 动态路由

文章目录 配置管理引入jar包添加 bootstrap.yaml 文件配置在application.yaml 中添加自定义信息nacos 配置信息 配置热更新采用第一种配置根据服务名确定配置文件根据后缀确定配置文件 动态路由DynamicRouteLoaderNacosConfigManagerRouteDefinitionWriter 路由配置 配置管理 …...

前端知识速记:节流与防抖

前端知识速记:节流与防抖 什么是防抖? 防抖是一种控制事件触发频率的方法,通常用于处理用户频繁触发事件的场景。防抖的核心思想是将多个连续触发事件合并为一个事件,以减少执行次数。它在以下场景中特别有效: 输入…...

2.攻防世界PHP2及知识点

进入题目页面如下 意思是你能访问这个网站吗? ctrlu、F12查看源码,什么都没有发现 用kali中的dirsearch扫描根目录 命令如下,根据题目提示以及需要查看源码,扫描以php、phps、html为后缀的文件 dirsearch -u http://61.147.17…...

【ubuntu】双系统ubuntu下一键切换到Windows

ubuntu下一键切换到Windows 1.4.1 重启脚本1.4.2 快捷方式1.4.3 移动快捷方式到系统目录 按前文所述文档,开机默认启动ubuntu。Windows切换到Ubuntu直接重启就行了,而Ubuntu切换到Windows稍微有点麻烦。可编辑切换重启到Windows的快捷方式。 1.4.1 重启…...

C#属性和字段(访问修饰符)

不同点逻辑性/灵活性存储性访问性使用范围安全性属性(Property)源于字段,对字段的扩展,逻辑字段并不占用实际的内存可以被其他类访问对接收的数据范围做限定,外部使用增加了数据的安全性字段(Field)不经过逻辑处理占用内存的空间及位置大部分字段不能直接被访问内存使用不安全 …...

Androidstdio-真机调试

显示隐藏设备 手机通过数据线插入电脑 Androidstdio设置中下载USB驱动 选择下载的驱动 更新完成后,在编译器查看,此时真机已经显示出来了 调试app可以在日志中查看日志,详细日志查看方法看前面的帖子 如果有这种日志输出,运行到此…...

2025年美赛B题-结合Logistic阻滞增长模型和SIR传染病模型研究旅游可持续性-成品论文

模型设计思路与创新点: 建模的时候应该先确定我们需要建立什么类的模型?优化类还是统计类?这个题需要大量的数据分析,因此我们可以建立一个统计学模型。 统计学建模思路:观察规律,建立模型,参…...

数据结构【链栈】

基于 C 实现链表栈:原理、代码与应用 一、引言 栈就是一个容器,可以当场一个盒子,只能一个一个拿,一个一个放,而且是从上面放入。 有序顺序栈操作比较容易【会了链栈之后顺序栈自然明白】,所以我们这里只…...

MediaPipe与YOLO已训练模型实现可视化人脸和手势关键点检测

项目首页 - ZiTai_YOLOV11:基于前沿的 MediaPipe 技术与先进的 YOLOv11 预测试模型,精心打造一款强大的实时检测应用。该应用无缝连接摄像头,精准捕捉画面,能即时实现人脸检测、手势识别以及骨骼关键点检测,将检测结果实时、直观地…...

使用 SpringBoot+Thymeleaf 模板引擎进行 Web 开发

目录 一、什么是 Thymeleaf 模板引擎 二、Thymeleaf 模板引擎的 Maven 坐标 三、配置 Thymeleaf 四、访问页面 五、访问静态资源 六、Thymeleaf 使用示例 七、Thymeleaf 常用属性 前言 在现代 Web 开发中,模板引擎被广泛用于将动态内容渲染到静态页面中。Thy…...

pytorch深度Q网络

人工智能例子汇总:AI常见的算法和例子-CSDN博客 DQN 引入了深度神经网络来近似Q函数,解决了传统Q-learning在处理高维状态空间时的瓶颈,尤其是在像 Atari 游戏这样的复杂环境中。DQN的核心思想是使用神经网络 Q(s,a;θ)Q(s, a; \theta)Q(s,…...

list的使用,及部分功能的模拟实现(C++)

目录(文章中"节点"和"结点"是同一个意思) 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 list element access 1.2.5 list modifiers 1.2.6 list…...

makailio-alias_db模块详解

ALIAS_DB 模块 作者 Daniel-Constantin Mierla micondagmail.com Elena-Ramona Modroiu ramonaasipto.com 编辑 Daniel-Constantin Mierla micondagmail.com 版权 © 2005 Voice Sistem SRL © 2008 asipto.com 目录 管理员指南 概述依赖 2.1 Kamailio 模块 2.2 外…...

【AI】DeepSeek 概念/影响/使用/部署

在大年三十那天,不知道你是否留意到,“deepseek”这个词出现在了各大热搜榜单上。这引起了我的关注,出于学习的兴趣,我深入研究了一番,才有了这篇文章的诞生。 概念 那么,什么是DeepSeek?首先百…...

算法随笔_35: 每日温度

上一篇:算法随笔_34: 最后一个单词的长度-CSDN博客 题目描述如下: 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升…...

人工智能入门课【手写自注意力机制】

原理 自注意力(Self-Attention)是一种强大的机制,广泛应用于自然语言处理、计算机视觉等领域,尤其是在Transformer架构中发挥了关键作用。它的核心思想是让模型能够动态地关注输入序列中不同位置之间的关系,从而更好地…...

记7(激活函数+多层神经网络+梯度下降法及其优化

目录 1、激活函数1.1、sigmoid函数:2端饱和,下面2个函数都要幂运算,运算速度会比较慢1.2、ReLU函数(Rectified Linear Unit,修正线性单元)1.3、PReLU函数(Parameteric Rectified Linear Unit&am…...

Qt u盘自动升级软件

Qt u盘自动升级软件 Chapter1 Qt u盘自动升级软件u盘自动升级软件思路:step1. 获取U盘 判断U盘名字是否正确, 升级文件是否存在。step2. 升级step3. 升级界面 Chapter2 Qt 嵌入式设备应用程序,通过U盘升级的一种思路Chapter3 在开发板上运行的…...

关于低代码技术架构的思考

我们经常会看到很多低代码系统的技术架构图,而且经常看不懂。是因为技术架构图没有画好,还是因为技术不够先进,有时候往往都不是。 比如下图: 一个开发者,看到的视角往往都是技术层面,你给用户讲React18、M…...

如何使用 ChatBox AI 简化本地模型对话操作

部署模型请看上一篇帖子:本地部署DeepSeek教程(Mac版本)-CSDN博客 使用 ChatBox AI 简化本地模型对话操作: 打开 ChatBox AI 官网:Chatbox AI官网:办公学习的AI好助手,全平台AI客户端&#xf…...

缩位求和——蓝桥杯

1.题目描述 在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确。 比如:248153720248153720 把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是 1 位数,得 24814>145 156 56 而…...

hexo部署到github page时,hexo d后page里面绑定的个人域名消失的问题

Hexo 部署博客到 GitHub page 后,可以在 setting 中的 page 中绑定自己的域名,但是我发现更新博客后绑定的域名消失,恢复原始的 githubio 的域名。 后面搜索发现需要在 repo 里面添加 CNAME 文件,内容为 page 里面绑定的域名&…...

neo4j入门

文章目录 neo4j版本说明部署安装Mac部署docker部署 neo4j web工具使用数据结构图数据库VS关系数据库 neo4j neo4j官网Neo4j是用ava实现的开源NoSQL图数据库。Neo4作为图数据库中的代表产品,已经在众多的行业项目中进行了应用,如:网络管理&am…...

代码随想录——回溯

文章目录 组合组合总数电话号码的字母组合组合总数组合总数Ⅱ分割回文串复原IP地址子集子集Ⅱ非递减子序列去重的实现方法方法 1:**排序 跳过重复元素**方法 2:**使用哈希表或数组记录已使用的数字** 去重的完整示例总结本题代码 全排列全排列Ⅱ重新安排…...

独立游戏RPG回顾:高成本

刚看了某纪录片, 内容是rpg项目的回顾。也是这个以钱为核心话题的系列的最后一集。 对这期特别有代入感,因为主角是曾经的同事,曾经在某天晚上听过其项目组的争论。 对其这些年的起伏特别的能体会。 主角是制作人,在访谈中透露这…...

SQLModel入门

目录 概述快速开始官方教程简单使用样例 概述 SQLModel 是一个 ORM 框架,其基于 SQLAlchemy 和 Pydantic,其中 SQLALchemy 提供底层 ORM 能力,Pydantic 提供类型校验能力,SQLModel 中,一个 SQLModel model 既是一个 S…...

关于MySQL InnoDB存储引擎的一些认识

文章目录 一、存储引擎1.MySQL中执行一条SQL语句的过程是怎样的?1.1 MySQL的存储引擎有哪些?1.2 MyIsam和InnoDB有什么区别? 2.MySQL表的结构是什么?2.1 行结构是什么样呢?2.1.1 NULL列表?2.1.2 char和varc…...

【学习笔记】深度学习网络-正则化方法

作者选择了由 Ian Goodfellow、Yoshua Bengio 和 Aaron Courville 三位大佬撰写的《Deep Learning》(人工智能领域的经典教程,深度学习领域研究生必读教材),开始深度学习领域学习,深入全面的理解深度学习的理论知识。 在之前的文章中介绍了深度学习中用…...

NVIDIA (英伟达)的 GPU 产品应用领域

游戏娱乐领域 PC 游戏:NVIDIA 的 GeForce 系列 GPU 是 PC 游戏玩家的首选之一。能实现实时光线追踪、高分辨率渲染等,使游戏画面更加逼真,如《赛博朋克 2077》等支持光线追踪的游戏,在 NVIDIA GPU 的加持下,可呈现出真…...

Docker快速部署高效照片管理系统LibrePhotos搭建私有云相册

文章目录 前言1.关于LibrePhotos2.本地部署LibrePhotos3.LibrePhotos简单使用4. 安装内网穿透5.配置LibrePhotos公网地址6. 配置固定公网地址 前言 想象一下这样的场景:你有一大堆珍贵的回忆照片,但又不想使用各种网盘来管理。怎么办?别担心…...

goframe 多语言国际化解决方案

项目背景 本项目采用基于JSON配置的多语言国际化(i18n)解决方案,支持多种语言的无缝切换和本地化。 目录结构 manifest/ └── i18n/├── zh.json # 简体中文├── zh-tw.json # 繁体中文├── en.json # 英语├…...

mysql如何修改密码

在MySQL中修改密码可以通过多种方式完成,具体取决于你的MySQL版本和你是否有足够的权限。以下是一些常用的方法来修改MySQL用户的密码: 方法1: 使用ALTER USER命令 这是最常用的方法,适用于MySQL 5.7及以上版本。 ALTER USER usernameloca…...

17.2 图形绘制8

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。 17.2.10 重绘 先看以下例子: 【例 17.28】【项目:code17-028】绘制填充矩形。 private void button1_Clic…...

Java基础知识总结(三十八)--读取数据

使用Reader体系,读取一个文本文件中的数据。返回 -1 ,标志读到结尾。 import java.io.*; class { public static void main(String[] args) throws IOException { /* 创建可以读取文本文件的流对象,让创建好的流对象和指定的文件相关联。…...

【并查集】

并查集(Disjoint Set Union,DSU)是一种用于处理不相交集合的数据结构,主要支持两种操作:查找(Find)和合并(Union)。它在解决连通性问题、图论问题以及动态连通性等问题时…...

SQL NOW() 函数详解

SQL NOW() 函数详解 引言 在SQL数据库中,NOW() 函数是一个常用的日期和时间函数,用于获取当前的时间戳。本文将详细介绍 NOW() 函数的用法、参数、返回值以及在实际应用中的注意事项。 函数概述 NOW() 函数返回当前的日期和时间,格式为 Y…...

[EAI-023] FAST,机器人动作专用的Tokenizer,提高VLA模型的能力和训练效率

Paper Card 论文标题:FAST: Efficient Action Tokenization for Vision-Language-Action Models 论文作者:Karl Pertsch, Kyle Stachowicz, Brian Ichter, Danny Driess, Suraj Nair, Quan Vuong, Oier Mees, Chelsea Finn, Sergey Levine 论文链接&…...

Rust 条件语句

Rust 条件语句 在编程语言中,条件语句是进行决策和实现分支逻辑的关键。Rust 语言作为一门系统编程语言,其条件语句的使用同样至关重要。本文将详细介绍 Rust 中的条件语句,包括其基本用法、常见场景以及如何避免常见错误。 基本用法 Rust…...

Windows 上安装 PostgreSQL

Windows 上安装 PostgreSQL PostgreSQL 是一款功能强大的开源对象-关系型数据库系统,它具有出色的扩展性和稳定性。本文将详细介绍在 Windows 操作系统上安装 PostgreSQL 的步骤和注意事项。 1. 准备工作 在开始安装 PostgreSQL 之前,请确保您的计算机满足以下要求: 操作…...

UE 5.3 C++ 对垃圾回收的初步认识

一.UObject的创建 UObject 不支持构造参数。 所有的C UObject都会在引擎启动的时候初始化,然后引擎会调用其默认构造器。如果没有默认的构造器,那么 UObject 将不会编译。 有修改父类参数的需求,就使用指定带参构造 // Sets default value…...

解码,蓝桥杯2020G

a2b 解码后&#xff1a;aab ​ #include<iostream> using namespace std; typedef struct Node {char data;int size;Node* next; }Node,*Linklist; char* scan(char str[],int size) {int i 0;Linklist head new Node;Linklist rear head;while (i<size-1) {Lin…...