基于深度学习的多模态MRI图像脑小血管病标志物量化分析与临床 风险因素研究
一、注释笔记
1. 文本高亮 (Page 4) VB-Net模型
2. 便签1 (Page 4) 标注:1. VB.NET 简介 (1)全称:Visual Basic .NET,是微软 .NET 框架下的编程语言之一。 (2)特点:面向对象:支持类、继承、多态等面向对象特性。 集成开发环境(IDE):通常与 Visual Studio 结合使用,提供强大的开发工具。 跨平台:通过 .NET Core 或 .NET 5+,可开发跨平台应用程序。 与 .NET 生态集成:可调用丰富的 .NET 类库,支持 Web、桌面、移动等多领域开发。 2. 基于 VB.NET 构建模型 在 VB.NET 中,模型通常指应用程序的逻辑结构或数据结构。以下是构建模型的常见方法: (1) 面向对象模型 类(Class):定义对象的属性和方法。 继承(Inheritance):通过 Inherits 关键字实现类的继承。 接口(Interface):定义类的行为规范,通过 Implements 关键字实现。 (2) 数据模型 与数据库交互:通过 ADO.NET 或 Entity Framework(需 C#/VB.NET 混合项目)访问数据库。 数据绑定:在 Windows Forms 或 WPF 应用中,将数据模型绑定到 UI 控件。 (3) 领域模型(Domain Model) 业务逻辑抽象:将业务规则封装到模型中,例如订单处理、用户认证等。 设计模式:使用工厂模式、单例模式等设计模式优化模型结构。
3. 文本高亮 (Page 4) CSVD
4. 文本高亮 (Page 4) 脑微出血(CMBs)(平均召回率 = 0.778;平均精确度=0.758)和血管周围间隙(PVS)(平均召回率= 0.953;平 均精确度= 0.923)在召回率和精确度方面优于腔隙性脑梗死
5. 便签2 (Page 4)标注:脑小血管病(CSVD)的影像学标志物是诊断和评估该疾病的关键指标,主要包括以下几种: 1. 腔隙(Lacunes) 定义:由小穿支动脉闭塞引起的直径3-15 mm的脑实质梗死灶。 影像学表现:T1WI低信号、T2WI和FLAIR高信号,周围可见胶质增生带。 临床意义:腔隙是CSVD最常见的标志物之一,与认知障碍和运动功能障碍密切相关。 2. 脑白质高信号(White Matter Hyperintensities, WMH) 定义:脑白质区域T2WI和FLAIR上的高信号区域,反映脱髓鞘和轴突损伤。 影像学表现:T2WI和FLAIR高信号,T1WI等或低信号。 临床意义:WMH与年龄增长、高血压和认知功能下降显著相关。 3. 脑微出血(Cerebral Microbleeds, CMBs) 定义:微小血管破裂导致的含铁血黄素沉积,直径2-5 mm。 影像学表现:T2*WI或SWI序列上的低信号灶。 临床意义:CMBs是脑淀粉样血管病和高血压性血管病变的标志,与卒中风险增加相关。 4. 血管周围间隙扩大(Enlarged Perivascular Spaces, EPVS) 定义:围绕脑小血管的液体间隙扩大,直径>2 mm。 影像学表现:T2WI和FLAIR上的线状或卵圆形高信号,与血管走行一致。 临床意义:EPVS与年龄、高血压和认知功能下降相关,尤其在基底节区。 5. 脑萎缩(Brain Atrophy) 定义:脑体积减少,包括全脑萎缩和局部区域萎缩。 影像学表现:T1WI上脑室扩大、脑沟增宽。 临床意义:脑萎缩是CSVD晚期的表现,与认知功能严重受损相关。 6. 皮层表面铁沉积(Cortical Superficial Siderosis, cSS) 定义:皮层表面含铁血黄素沉积,反映反复的蛛网膜下腔出血。 影像学表现:SWI序列上的皮层表面线状低信号。 临床意义:cSS是脑淀粉样血管病的特异性标志,与认知功能下降和卒中风险增加相关。 7. 新近皮质下小梗死(Recent Small Subcortical Infarcts, RSSI) 定义:近期发生的直径
6. 文本下划线 (Page 5) 年龄与 CSVD 总负荷评分呈正相关,总胆固 醇与 CSVD 总负荷评分呈负相关
7. 文本下划线 (Page 5) 年 龄与 EPVS 的数量,LIs 和 WMH 的总体积呈正相关;年龄与各脑区 WMH 体积 均呈正相关,SBP 数值与 JVWMH、PVWMH 的体积呈正相关;年龄与 CSVD 总 负荷评分呈正相关,总胆固醇与其呈负相关。CSVD 总负荷评分越高,患腔隙性
8. 文本下划线 (Page 11) 磁共振成像(MRI)扫描是检测 CSVD 的主要诊断工具 9. 文本下划线 (Page 11) CSVD 拥有许多影像学指标,其中包括脑微小出血 (CMBS)、血管周围空间增大(EPVS)、腔隙性脑梗死(LIs)以及脑白质高信号 (WMH)[3]。
10. 文本下划线 (Page 11)风险分层,进一步帮助治疗方案的制定
11. 文本下划线 (Page 12) 使用二维卷积神经网络(CNN)
12. 便签3 (Page 12)标注:CNN(卷积神经网络,Convolutional Neural Network) 是一种专门用于处理具有网格 结构数据(如图像、视频等)的深度学习模型,在计算机视觉领域取得了巨大成功。以下是关于 CNN 的详细介绍: 一、CNN 的核心结构 卷积层(Convolutional Layer) 1、作用:提取输入数据(如图像)的局部特征。 2、原理:通过卷积核(滤波器)在输入数据上滑动,计算卷积操作,生成特征图(Feature Ma p)。 3、特点: (1)参数共享:同一卷积核在输入的不同位置共享参数,减少模型参数数量。 (2)局部连接:每个神经元仅与输入数据的局部区域连接,捕捉局部特征。 (3)激活函数(Activation Function) 作用:引入非线性,增强模型的表达能力。 常用函数:ReLU(Rectified Linear Unit)、Sigmoid、Tanh 等。 (4)池化层(Pooling Layer) 作用:降低特征图的维度,减少计算量,防止过拟合。 常用方法: 最大池化(Max Pooling):取局部区域的最大值。 平均池化(Average Pooling):取局部区域的平均值。 (5)全连接层(Fully Connected Layer) 作用:将卷积层和池化层提取的特征进行整合,输出最终分类结果。 特点:每个神经元与前一层的所有神经元连接。 (6)归一化层(Normalization Layer) 作用:加速训练过程,提高模型稳定性。 常用方法:Batch Normalization。 二、CNN 的工作原理 1、前向传播(Forward Propagation) 输入数据依次通过卷积层、激活函数、池化层等,最终得到输出结果。 2、反向传播(Backpropagation) 根据损失函数计算误差,通过梯度下降法更新网络参数,使模型逐渐逼近最优解。 3、训练过程 (1)数据预处理:对输入数据进行归一化、增强等操作。 (2)模型初始化:随机初始化网络参数。 (3)迭代优化:通过多次前向传播和反向传播,调整模型参数。 三、CNN 的优势 1、自动特征提取:无需手动设计特征,模型自动学习数据中的模式。 2、参数共享:减少模型参数数量,降低过拟合风险。 3、平移不变性:卷积操作对输入数据的平移具有不变性,适合处理图像等数据。 4、层次化特征表示:低层卷积层提取边缘、纹理等低级特征,高层卷积层提取更抽象的高级特征。 四、CNN 的应用领域 1、图像分类:如手写数字识别(MNIST 数据集)、图像分类(ImageNet 数据集)。 2、目标检测:如 YOLO、Faster R-CNN 等模型,用于检测图像中的目标物体。 3、图像分割:如 U-Net、Mask R-CNN 等模型,用于对图像进行像素级分割。 4、人脸识别:如 FaceNet、DeepFace 等模型,用于人脸验证和识别。 5、自然语言处理:通过一维卷积操作处理文本数据,如情感分析、文本分类。 五、经典的 CNN 模型 1、LeNet-5 提出者:Yann LeCun 特点:最早的卷积神经网络之一,用于手写数字识别。 2、AlexNet 提出者:Alex Krizhevsky 等 特点:在 ImageNet 竞赛中取得优异成绩,推动了深度学习的发展。 3、VGGNet 提出者:Visual Geometry Group 特点:使用小卷积核(3x3)堆叠,网络深度较深。 4、GoogLeNet(Inception 系列) 提出者:Google 特点:引入 Inception 模块,通过并行卷积操作提取多尺度特征。 5、ResNet(残差网络) 提出者:Kaiming He 等 特点:引入残差连接,解决了深层网络训练中的梯度消失问题。 6、DenseNet 特点:每个层都与前面所有层直接连接,进一步增强了特征复用。 六、CNN 的发展趋势 1、轻量化模型:如 MobileNet、ShuffleNet 等,适用于移动设备和嵌入式系统。 2、注意力机制:结合注意力机制(如 SENet、CBAM),提高模型对重要特征的关注。 3、自监督学习:通过无监督学习方式预训练模型,减少对标注数据的依赖。 4、神经架构搜索(NAS):自动搜索最优的网络结构,提高模型性能。 七、CNN 的挑战 1、数据需求:需要大量标注数据进行训练,数据获取和标注成本较高。 2、计算资源:训练深度 CNN 模型需要大量计算资源,尤其是 GPU。 3、可解释性:CNN 模型被视为“黑箱”,难以解释其决策过程。 八、总结 卷积神经网络(CNN)是深度学习领域的重要模型,尤其在计算机视觉任务中表现出色。通过卷 积操作和层次化特征表示,CNN 能够自动提取数据中的模式,实现高效的图像识别、目标检测和 图像分割等功能。随着技术的不断发展,CNN 模型在性能、效率和可解释性方面不断改进,为人 工智能应用提供了强大的支持。
13. 文本下划线 (Page 15) 磁共振成像检查包括 T1 加权磁共振成像(T1WI)、T2 加权磁共振成像 (T2WI)、T2-流体衰减反转恢复(T2-FLAIR)、弥散加权成像(DWI)和磁敏 感加权成像(SWI),每种成像都能反映特定的组织特征
14. 便签4 (Page 15)标注:1. T1加权成像(T1WI) (1)成像原理: T1WI通过调整脉冲序列的重复时间(TR)和回波时间(TE),突出组织之间的T1弛豫时间差异。 短TR(2000 ms)和长TE(>80 ms),突出组织之间的T2弛豫时间差异。 T2弛豫时间长的组织(如水)信号强,而T2弛豫时间短的组织(如脂肪)信号弱。 (2)组织特征: 高信号:水肿、炎症、囊肿、脑脊液。 低信号:钙化、出血(急性期含氧合血红蛋白)、铁沉积。 (3)临床应用: 检测脑水肿、炎症、脱髓鞘病变(如多发性硬化)。 评估肿瘤水肿范围。 2. T2-流体衰减反转恢复(T2-FLAIR) (1)成像原理: T2-FLAIR在T2WI基础上增加一个180°反转脉冲,抑制自由水信号(如脑脊液),使脑脊液呈低 信号,而结合水信号(如水肿)仍保持高信号。 (2)组织特征: 高信号:结合水(如水肿、炎症)。 低信号:自由水(脑脊液)。 (3)临床应用: 增强脑室旁白质病变(如脱髓鞘病变)的对比度。 检测脑室旁梗死、脑膜炎、脑炎。 3. 弥散加权成像(DWI) (1)成像原理: DWI通过施加弥散敏感梯度,检测水分子的布朗运动。 急性期缺血时,细胞毒性水肿导致水分子弥散受限,信号增高。 (2)组织特征: 高信号:急性期梗死、细胞毒性水肿。 低信号:正常脑组织、慢性期梗死(弥散恢复)。 (3)临床应用: 早期诊断急性脑梗死(发病后数分钟至数小时)。 评估肿瘤细胞密度(如高级别胶质瘤)。 4. 磁敏感加权成像(SWI) (1)成像原理: SWI利用不同组织间的磁敏感差异(如脱氧血红蛋白、含铁血黄素、钙化)产生相位差异,通过 后处理生成高对比图像。 (2)组织特征: 高信号:钙化、出血(含正铁血红蛋白)。 低信号:静脉血管、出血(含脱氧血红蛋白)、铁沉积。 (3)临床应用: 检测微小出血灶(如脑微出血、海绵状血管瘤)。 评估静脉血管畸形(如静脉窦血栓)。
15. 文本下划线 (Page 15) U-Net 是经典的编码解码网络,编 码阶段将图像压缩为由特征组成的 feature maps,然后再经过解码阶段将特征解 码为与原始图像尺寸一样的分割结果[8]。
16. 文本下划线 (Page 15) 提取图像特征信息的收缩路径,另一部分则是对待分割位置进行精确图 像映射的扩展路径
17. 文本下划线 (Page 15) 网络通过多层卷积层和最大池化层,将输入图像逐级 转化为高维特征表示,这个过程被称为编码或下采样。然后,通过上采样和转置 卷积操作,特征表示再次被恢复得越来越接近原始图像的大小,这个过程称为解 码。在解码过程中,还会通过跳层连接将相应阶段的编码特征图与解码特征图进 行融合,此为 U-Net 的一个关键步骤,既能避免网络训练过程中出现梯度消失的 问题,也能为解码过程中图像映射增加辅助信息。
18. 文本下划线 (Page 19) 脑白质 高信号(WMH)被定义为在 T2WI 和 T2 FLAIR 序列上表现为高信号,同时在 T1WI 序列上表现为等信号或低信号[12]。
19. 文本下划线 (Page 19) WMH 的自动量化方法可以分为无监督和有监督两类。无 监督方法通常利用强度特征进行聚类并且不需要额外的训练,而有监督方法可以 提取更高级别的信息并且依赖于足够的手动描绘数据作为训练的基础事实。
20. 文本下划线 (Page 20) 近期皮层下梗死(RSSI)表现为位于穿通动脉分布区的近期小梗死。
21. 文本下划线 (Page 20) 在 MRI 图像中,RSSI 的呈现形式主要是在 T1 WI 上表现为低信 号,而在 T2WI 和 T2-FLAIR 上呈现为高信号。
22. 文本下划线 (Page 21) 血管周围间隙(PVS)在 T1WI 上表现为低信号,在 T2WI 上表现为高信 号阴影。
23. 文本下划线 (Page 22) 脑萎缩(Brain atrophy)是指由于各种因素导致的脑组织结构器质性病变从 而产生萎缩的现象
24. 文本下划线 (Page 26) ,VB-Net对WMH和RSSI的分割结果在DSC、 召回率和精确度方面与两名医师勾画情况高度一致。
25. 文本下划线 (Page 31) 根据多因素线性回归模型,年龄 与 EPVS 的数量、LIs 和 WMH 的总体积呈正相关
26. 文本下划线 (Page 31)在不同脑 区WMH体积的线性回归分析中,年龄与各脑区WMH体积呈正相关,SBP与 JVWMH 和 PVWMH 体积呈正相关(P < 0.05)(表 3-5)(图 3-5)。 27. 文本下划线 (Page 31) 年 龄与 CSVD 总负荷评分呈正相关,TC 与 CSVD 总负荷评分呈负相关
28. 文本下划线 (Page 35) WMH 体积随年龄增长而增加
29. 文本下划线 (Page 35) 载脂蛋白 A1、b 在一定程度上对 CSVD 总负荷评分有影响
30. 文本下划线 (Page 35) 高胆固醇血症或高脂血症患者卒中 时WMH严重程度较低,表明高脂血症可能对CSVD疾病具有相对保护作用 的可能性
31. 文本下划线 (Page 36) MRI CSVD 智能 分析系统可以对 CSVD 的各种亚型进行检测、分割、量化和评分。它可应用 于不同亚型的不同MRI 序列,包括:(1)WMH病变范围评估、体积量化和 Fazekas 评分计算;(2)RSSI;(3)LIs;以及(4)自动检测 EPVS、脑内 精确定位和病变定量分析(包括数量、总体积)。
32. 文本下划线 (Page 37) 本研究仅采用一种深 度学习算法,未对不同算法对 CSVD 影像学标志物的分割性能进行比较;
33. 文本高亮 (Page 48) 深度学习网络主要由如下部分组成:卷积神经网络(convolutional neural network,CNN)、对抗生成网络(recurrent neural network,GAN)、循环神 经网络(recurrent neural network,RNN)以及深度连接神经网络(Deep neural network,DNN)。
34. 文本下划线 (Page 48) 与传统神经网络相比,在输入层及全连接层和输出层的基础上增加了 卷积层、归一化层、池化层三个步骤。
35. 文本下划线 (Page 49) 近期皮层下脑梗死(RSSI)定义为短时间内发生于穿支动脉附近的梗 死,其病灶体积较小,在 T1WI 系列中展示为低信号,在 T2WI 和 FLAIR 系列 中表示为高信号,
36. 文本下划线 (Page 50) 腔隙性脑梗死(LIs)是脑小血管病磁共振图像的经典特征,在各类脑梗死 亚型之中,腔隙性脑卒中在缺血性脑卒中的各种亚型占有特殊的地位,其占比约 25%[18]。
37. 文本下划线 (Page 50)血管周围间隙(PVS)在 T1WI 上呈低信号,T2WI 上表现为沿穿支动脉走行分 布的高信号影,类似于脑脊液信号,常好发于半卵圆中心、基底节区和中脑,其 与镜像平面平行时呈线性,与镜像平面垂直时呈点状[2]
38. 文本下划线 (Page 50) 与 WMH 与 CMBS 相比,EPVS 缺乏可用于训练的 EPVS 手动 描绘模型, Frangi 过滤器是早期用于手动分割 EPVS 的方法,其功能单一,只 能对一个病灶进行分割,低准确率加上耗时长的局限性
39. 文本下划线 (Page 51) 运用 3D 回归卷积神经网络的自动评分量化 EPVS 数量,该方法与 传统视觉评估之间的组内相关性系数(ICC)在 0.75 至 0.88 之间
40. 文本下划线 (Page 51) 在 T2WI 和 FLAIR 序列中,白质高信号(WMH)呈现出高信号,而在 T1WI 中,它表现为等信号或者低信号[3]。
41. 文本下划线 (Page 52) 基于 CNN 网络框架提出的另一种用于分割颅内白质 高信号和其他共存病变的算法称为 2D VB-Net,它在分割 WMH 和其他颅内病变 方面优于其他先进算法(uRes-Net、3D V-Net 和 Visual Ge-ometering Group networks),它在具有厚层磁共振(MR)图像的数据集和 2017 年具有薄层磁共 振图像的医学图像计算和计算机辅助干预 WMH 分割挑战数据集上得到了很好 的验证。
42. 文本下划线 (Page 52)脑微出血(CMBs) 是由血管壁受损引发的出血导致的含铁血黄素积聚,在 GRE-T2 或 SWI 上,它体现为直径在 2 到 5mm 之间的均匀而统一的椭圆形低信 号或者信号消失,且病灶周围未见到水肿状况[2]
43. 文本下划线 (Page 53) 由于 MRI 序列上 CSVD 免疫生物标志物的视觉评级耗时费力,以及 ROI 的手动描绘,已经发明了越来越多的 CSVD 特征的量化方法。量化方法取决 于 CSVD 的性能指标和量化目的(检测或分割)。
44. 文本高亮 (Page 55) CSVD 成像生物标志物是各种神经和精 神疾病的风险因素,基于深度学习的自动量化比视觉评分更直观地反映疾病的进 展和严重程度,自动量化提供了更详细的信息,如位置和体积,可以更好地制定 治疗方案,促进患者预后。
二、文献综述
摘要: 脑小血管病(CSVD)是一种严重危害人类健康的常见疾病,基于传统的成像 方式精确诊断CSVD仍具有一定局限性,为了取代主观和费力的图像分割和视觉 评级方法,应用深度学习算法自动扫描和提取CSVD影像学标志物愈发成为主流 趋势,这些标志物包括腔隙 (LIs)、血管周围间隙 (PVS)、白质高信号(WMH)、 脑微出血(CMBs)、近期皮层下脑梗死(RSSI),提取出的影像学标志物可与临床风 险因素特异结合进行病因分析。此外,总CSVD负荷评分近年来也被认为是引发 卒中的重要预测因子。
关键词: 多模态、磁共振、脑小血管病、深度学习、危险因素、影像学特征
腔隙性脑卒中占所有缺血性脑卒中的25%-30%,其病理基础主要涉及穿支动脉闭塞导致的脑实质小梗死灶。脑小血管病(CSVD)作为腔隙性卒中的核心病理机制,涵盖腔隙性梗死(LIs)、脑白质高信号(WMH)、扩大血管周围间隙(EPVS)及微出血(CMBs)等影像学标志物。传统评估方法依赖人工勾画,存在主观性强、效率低等局限。深度学习技术的引入,为CSVD的精准诊断与风险分层提供了新工具。
深度学习模型(如卷积神经网络,CNN)通过整合T1加权、T2加权、FLAIR及DWI等多模态MRI数据,显著提升了CSVD病变的检测灵敏度与特异性。CSVD总负荷评分(CSVD-TS)整合LIs数量、WMH体积、EPVS分级及CMBs计数等多项指标,通过加权求和实现疾病严重程度的数字化表达。深度学习模型可自动提取上述参数,生成标准化评分,其与临床神经功能缺损评分(如NIHSS)的相关性系数达0.65(p<0.001)。腔隙性卒中组在CSVD-TS及各影像学标志物指标上均显著高于对照组(p<0.01)。Logistic回归分析表明,CSVD-TS每增加1分,腔隙性卒中风险升高1.8倍(OR=1.8, 95%CI 1.4-2.3)。年龄是CSVD的核心驱动因素。每增加10岁,WMH体积增长约20%,EPVS分级提升1级(p<0.001)。此外,年龄与脑室旁(PVWMH)、深部(DWMH)及脑室周围深部(JCWMH)WMH体积均呈显著正相关。收缩压(SBP)每升高10 mmHg,JVWMH与PVWMH体积分别增加8%与12%(p<0.01)。长期高血压通过破坏血脑屏障完整性,加速WMH进展。多因素回归分析证实,年龄、SBP及CSVD-TS为腔隙性卒中的独立预测因子。基于上述参数构建的联合诊断模型,其曲线下面积(AUC)达0.89(95%CI 0.85-0.93),显著优于单一指标预测(p<0.001)。量化CSVD-TS有助于识别高危人群,指导个性化干预措施(如降压目标设定、抗血小板治疗强度调整),从而降低腔隙性卒中复发风险。
当前深度学习模型仍需解决数据异质性、标注成本高及临床验证不足等问题。未来研究应聚焦于多中心大样本验证、纵向队列分析及跨模态数据融合(如MRI与PET),以进一步提升模型的泛化能力。
结论
基于深度学习的多模态MRI技术为CSVD的精准评估提供了强大工具。通过量化CSVD-TS及整合人口学与临床因素,可有效预测腔隙性卒中风险,为临床决策提供科学依据。未来需深化技术探索,推动其在卒中预防与管理中的广泛应用。
- [1]古力孜巴·牙生. 基于机器学习的MRI影像组学在识别脑小血管病轻度认知障碍中的应用研究[D]. 导师:王云玲. 新疆医科大学, 2024.
- [2]李燕.Ⅰ型脑小血管病伴认知障碍多模态磁共振成像研究[D].安徽医科大学,2024.DOI:10.26921/d.cnki.ganyu.2024.002065.
- [3]杜静.脑小血管病患者卒中后早期认知障碍的多模态磁共振研究[D].上海交通大学,2019.DOI:10.27307/d.cnki.gsjtu.2019.003533.
- Chojdak-Łukasiewicz, Justyna et al. “Cerebral small vessel disease: A review.” Advances in clinical and experimental medicine : official organ Wroclaw Medical University vol. 30,3 (2021): 349-356. doi:10.17219/acem/131216
- van den Brink, Hilde et al. “Advanced MRI in cerebral small vessel disease.” International journal of stroke : official journal of the International Stroke Society vol. 18,1 (2023): 28-35. doi:10.1177/17474930221091879
- Wu, Liu-Yun et al. “Blood-based biomarkers of cerebral small vessel disease.” Ageing research reviews vol. 95 (2024): 102247. doi:10.1016/j.arr.2024.102247
技术学习:python
一、python中的数据容器
一种可以容纳多份数据的数据类型,容纳的每一份数据称之为一个元素。每一个元素可以时是任意类型的数据。如字符串、数字、布尔等。
数据容器根据特点的不同,如:是否支持重复元素、是否可以修改、是否有序等,分为5类,分别是:列表(list)、元组(tuple)、字符串(str)、集合(set)、字典(dict)
二、列表
1、列表的定义
基本语法:列表内的每一个数据,称为元素;以[ ]作为标识;列表内的每一个元素之间用, 逗号隔开
基本语法:
# 字面量
[元素1,元素2,···,元素n]
# 定义变量
mylist = [1,2,3,4]
# 定义空列表
mylist2 = []
2、嵌套列表的定义
支持嵌套,可以一次存储多个数据,且可以为不同的数据类型
my_list = [[1,2,3],[4,5,6]]
print(my_list)
print(type(my_list))
3、列表的位置下标索引
列表中的每一个元素都有其位置下标索引,只需按照下标索引即可取得对应位置的元素
列表的正向下标索引:从左往右,从0开始,依次递增
# 语法:列表[下标索引]
name_list = ['Tom','Lily','Rose']
print(name_list[0]) #结果:Tom
print(name_list[1]) #结果:Lily
print(name_list[2]) #结果:Rose
列表的下标索引----反向:从后往前,从-1开始,依次递减,-1,-2,-3······
name_list = ['Tom','Lily','Rose']
print(name_list[-3]) #结果:Tom
print(name_list[-2]) #结果:Lily
print(name_list[-1]) #结果:Rose
注:列表的嵌套中同样支持下标索引
4、列表的常用操作
(1)查找某元素的下标:查找指定元素在列表的下标,如果找不到,报错ValueError;
语法:列表.index(元素) index就是列表对象(变量)内置的方法(函数)
mylist = ["itcast","itheima","python"]
# 1.1查找某元素在列表内的下标索引
index = mylist.index("itheima")
print(f"itheima在列表中的下标索引值是:{index}")
# 1.2如果被查找的元素不存在,会报错
index = mylist.index("Hello")
print(f"Hello在列表中的下标索引值是:{index}")
(2)修改列表中特定位置的元素值:
语法:列表[下标] = 值 直接对指定下标(正向、反向下标均可)的值进行重新赋值或者修改
# 正向下标
my_list = [1,2,3]
my_list[0] = 5
print(my_list) # 结果:[5,2,3]
# 反向下标
my_list = [1,2,3]
my_list[-3] = 5
print(my_list) # 结果:[5,2,3]
(3)插入元素
语法:列表.insert(下标,元素),在指定的下标位置,插入指定的元素
my_list = [1,2,3]
my_list.insert(1,"itheima")
print(my_list) # 结果:[1,"itheima",3,4]
(4)追加元素1:此方法与下标无关,只追加到列表尾部
语法:列表.append(元素) 将指定元素追加到列表的尾部
my_list = [1,2,3]
my_list.append(4)
print(my_list) # 结果:[1,2,3,4]
my_list = [1,2,3]
my_list.append([4,5,6])
print(my_list) # 结果:[1,2,3,[4,5,6]]
(5)追加元素2:追加一批元素,依次增加
语法:列表.extend(其他数据容器),将其它数据容器的内容取出,依次追加到列表尾部
my_list = [1,2,3]
my_list.extend([4,5,6])
print(my_list) # 结果: [1,2,3,4,5,6]
(6)删除元素:语法1:del列表[下标]
语法2:列表.opp(下标) 取出元素后既有返回值,又删除了元素
# 1.方式1:del列表[下标]
del mylist[2]
print(f"列表删除元素后结果是:{mylist}")
# 2.方式2:列表。pop(下标)
mylist = ["itcast","itheima","python"]
print(f"通过pop方法取出元素后列表内容:{mylist},取出的元素是:{element}")
(7)删除某元素在列表的第一个匹配项,只删第一个且只删1个
语法:列表.remove(元素)
my_list = [1,2,3,2,3]
my_list.remove(2)
print(my_list) # 结果:[1,3,2,3]
(8)清空列表内容
语法:列表.clear()
my_list = [1,2,3]
my_list.clear()
print(my_list) # 结果:[]
(9)统计列表内有多少元素
语法:len(列表) 不是列表的功能,利用函数
my_list = [1,2,3,4,5]
print(len(my_list)) # 结果:5
(10)统计某元素在列表内的数量
语法:列表.count(元素)
my_list = [1,1,1,2,3]
print(my_list.count(1)) # 结果: 3
(11)列表基础操作总结练习
"""
演示列表常用操作的课后练习
"""
# 1.定义这个列表,并用变量接受它
mylist = [21,25,21,23,22,20]
# 2.追加一个数字31到列表的尾部
mylist.append(31)
# 3.追加一个新列表[29,33,30],到列表的尾部
mylist.extend([29,33,30])
# 4.取出第一个元素(应是21)
num1 = mylist[0]
print(f"从列表中取出来第一个元素,应该是21,实际上是:{num1}")
# 5.取出第一个元素(应是30)
num2 = mylist[-1]
print(f"从列表中取出来最后一个元素,应该是30,实际上是:{num2}")
# 6.查找元素31在列表中的下标位置
index = mylist.index(31)
print(f"元素31在列表中的下标位置是:{index}")
print(f"最后列表内容是:{mylist}")
(12)使用while循环遍历列表
def list_for_func():
my_list = ["传智教育","黑马程序员","python"]
index = 0
while index < len(my_list):
element = my_list[index]
print(f"列表的元素:{elememt}")
index += 1
list_while_func()
(13)使用for循环遍历列表
def list_for_func():
my_list = [1,2,3,4,5]
for element in my_list:
print(f"列表的元素有:{element}")
list_for_func
(14)for循环和while循环的对比
while循环和for循环,都是循环语句,但细节不同:
在循环控制上:
while循环可以自定循环条件,并自行控制
for循环不可以自定循环条件,只可以一个个从容器内取出数据
在无限循环上:
while循环可以通过条件控制做到无限循环
for循环理论上不可以,因为被遍历的容器容量不是无限的
在使用场景上:
while循环适用于:任何想要循环的场景
for循环适用于:遍历数据容器的场景或简单的固定次数循环场景
三、元组
1.元组的定义:定义元组使用小括号,使用逗号隔开各个数据,数据可以是不同的数据类型
2、元组不能被篡改
3、定义一个元素的元组时,在数据后面要添加逗号,如t2 = ('Hello',)
4、定义空元组
变量名称 = () 方式1
变量名称 = tuple() 方式2
5、元组的相关操作
# 元组的嵌套
t1 = ((1,2,3),(4,5,6))
print(f"t1的类型是:{type(t1)},内容是:{t1}")
# 下标索引取出内容
num = t1[1][2]
print(f"从嵌套元组中取出的数据是:{num}")
# 元组的操作:index查找方法
t2 = ("传智教育","黑马程序员","python")
index = t2.index("黑马程序员")
print(f"在元组t2中查找黑马程序员的下标是:{index}")
# 元组的操作:count统计方法
t3 = ("传智教育","黑马程序员","黑马程序员","python")
num = t3.count("黑马程序员")
print(f"在元组t7中统计黑马程序员的数量有:{num}个")
# 元组的操作:len函数统计元组元素数量
t4 = ("传智教育","黑马程序员","黑马程序员","黑马程序员","python")
num = len(t4)
print(f"t4元组中的元素有:{num}个")
# 元组的遍历:while
index = 0
while index < len(t4)
print(f"元组的元素有:{t4[index]}")
index += 1
# 元组的遍历:for
for element in t4:
print(f"元组的元素有:{element}")
四、字符串
1、字符串的下标索引:与列表、元组一样
# 通过下标获取特定位置字符
name = "itheima"
print(name[0]) # 结果 i
print(name[-1]) # 结果 a
2、与元组一样,字符串是一个:无法修改的数据容器
3、字符串的替换
语法:字符串.replace(字符串1,字符串2)
功能:将字符串内的全部字符串1替换为字符串2
注意:不是修改字符串本身,而是得到了一个新的字符串
my_str = "itheima and itcast"
new_my_str = my_str.replace("it","程序")
print(f"将字符串{my_str}替换得到{new_my_str}")
4、字符串的分割
语法:字符串.split(分隔符字符串)
功能:按照指定的分割符字符串,将字符串划分为多个字符串,并存入列表对象中
注意:字符串本身不变,而是得到了一个列表对象
my_str = "hello python itheima itcast"
my_str_list = my_str.split(" ")
print(f"将字符串{my_str}进行split切分后得到:{my_str_list}")
5、字符串的规整操作(去前后空格)
语法:字符串.strip(字符串)
my_str = " itheima and itcast "
print(my_str.strip()) # 结果:"itheima and itcast"
6、字符串的规整操作(去前后指定字符串)
语法:字符串.strip(字符串)
my_str = "12itheima and itcast21"
print(my_str.strip("12")) # 结果:"itheima and itcast"
注意:传入的是“12”,实际上是“1”和“2”都会移除
五、数据容器(序列)的切片
1、序列的定义
序列是指:内容连续、有序,可使用下标索引的的一类数据容器。如列表、元组、字符串均可视作序列。
2、序列的常用操作-切片
序列支持切片,即:列表、元组、字符串,均支持进行切片操作切片
切片:从一个序列中,取出一个子序列
语法:序列[起始下标:结束下标:步长]
表示从序列中,从指定位置开始,依次取出元素,到指定位置结束,得到一个新序列:
起始下标表示从何处开始,可以留空,留空视作从头开始
结束下标(不含)表示何处结束,可以留空,留空视作截取到结尾步长表示,依次取元素的间隔
步长1表示,一个个取元素
步长2表示,每次跳过1个元素取步长N表示,每次跳过N-1个元素取
步长为负数表示,反向取(注意,起始下标和结束下标也要反向标记)
注意:此操作不会影响序列本身,会得到一个新的序列
# 对list进行切片,从1开始,4结束,步长1
my_list = [0, 1, 2, 3, 4, 5, 6]
result1 = my_list[1:4] # 步长默认是1,所以可以省略不写
print(f"结果1:{result1}")
# 对tuple进行切片,从头开始,到最后结束,步长1
my_tuple = (0, 1, 2, 3, 4, 5, 6)
result2 = my_tuple[:] # 起始和结束不写表示从头到尾,步长为1可以省略
print(f"结果2:{result2}")
# 对str进行切片,从头开始,到最后结束,步长2
my_str = "01234567"
result3 = my_str[::2]
print(f"结果3:{result3}")
# 对str进行切片,从头开始,到最后结束,步长-1
my_str = "01234567"
result4 = my_str[::-1] # 等同于将序列反转了
print(f"结果4:{result4}")
# 对列表进行切片,从3开始,到1结束,步长-1
my_list = [0, 1, 2, 3, 4, 5, 6]
result5 = my_list[3:1:-1]
print(f"结果5:{result5}")
# 对元组进行切片,从头开始,到尾结束,步长-2
my_tuple = (0, 1, 2, 3, 4, 5, 6)
result6 = my_tuple[::-2]
print(f"结果6:{result6}")
六、集合
1、定义:大括号{ }, 用逗号隔开,会去重
2、集合的常用操作-修改
首先,因为集合是无序的,所以集合不支持:下标索引访问
但是集合和列表一样,是允许修改的
(1)添加新元素
语法:集合.add(元素)。将指定元素,添加到集合内
结果:集合本身被修改,添加了新元素
(2)移除元素
语法:集合.remove(元素),将指定元素,从集合内移除
结果:集合本身被修改,移除了元素
(3)从集合中随机取出元素
语法:集合.pop(),功能,从集合中随机取出一个元素
结果:会得到一个元素的结果。同时集合本身被修改,元素被移除
(4)清空集合
语法:集合.clear(),功能,清空集合
结果:集合本身被清空
(5)取出2个集合的差集
语法:集合1.difference(集合2),功能:取出集合1和集合2的差集(集合1有而集合2没有的)
结果:得到一个新集合,集合1和集合2不变
(6)消除2个集合的差集
语法:集合1.difference update(集合2)
功能:对比集合1和集合2,在集合1内,删除和集合2相同的元素
结果:集合1被修改,集合2不变
(7)集合的常用操作-修改
2个集合合并
语法:集合1union(集合2)
功能:将集合1和集合2组成新集合
结果:得到新集合,集合1和集合2不变
# 定义集合
my_set = {"传智教育", "黑马程序员", "itheima", "传智教育", "黑马程序员", "itheima", "传智教育", "黑马程序员", "itheima"}
my_set_empty = set() # 定义空集合
print(f"my_set的内容是: {my_set}, 类型是: {type(my_set)}")
print(f"my_set_empty的内容是: {my_set_empty}, 类型是: {type(my_set_empty)}")
# 添加新元素
my_set.add("Python")
my_set.add("传智教育")
print(f"my_set添加元素后结果是: {my_set}")
# 移除元素
my_set.remove("黑马程序员")
print(f"my_set移除黑马程序员后, 结果是: {my_set}")
# 随机取出一个元素
my_set = {"传智教育", "黑马程序员", "itheima"}
element = my_set.pop()
print(f"集合被取出元素是: {element}, 取出元素后: {my_set}")
# 清空集合, clear
my_set.clear()
print(f"集合被清空啦, 结果是: {my_set}")
# 取2个集合的差集
set1 = {1, 2, 3}
set2 = {1, 5, 6}
set3 = set1.difference(set2)
print(f"取出差集后的结果是: {set3}")
print(f"取差集后, 原有set1的内容: {set1}")
print(f"取差集后, 原有set2的内容: {set2}")
# 消除2个集合的差集
set1 = {1, 2, 3}
set2 = {1, 5, 6}
set1.difference_update(set2)
print(f"消除差集后, 集合1结果: {set1}")
print(f"消除差集后, 集合2结果: {set2}")
# 2个集合合并为1个
set1 = {1, 2, 3}
set2 = {1, 5, 6}
set3 = set1.union(set2)
print(f"2集合合并结果: {set3}")
print(f"合并后集合1: {set1}")
print(f"合并后集合2: {set2}")
# 统计集合元素数量len()
set1 = {1, 2, 3, 4, 5}
num = len(set1)
print(f"集合内的元素数量有: {num}个")
# 集合的遍历
# 集合不支持下标索引, 不能用while循环
# 可以用for循环
set1 = {1, 2, 3, 4, 5}
for element in set1:
print(f"集合的元素有: {element}")
七、字典
1、定义:使用{},存储的元素是:键值对,用逗号分隔 {key:value}一个元素是一个键值对
字典也不可以重复key
2、与集合一样,不能使用下标索引,但是可通过key值取得对应的Value
3、嵌套:key和value可以是任意数据类型(key不可为字典)
# 定义字典
my_dict1 = {"王力宏": 99, "周杰伦": 88, "林俊杰": 77}
# 定义空字典
my_dict2 = {}
my_dict3 = dict()
print(f"字典1的内容是:{my_dict1}, 类型:{type(my_dict1)}")
print(f"字典2的内容是:{my_dict2}, 类型:{type(my_dict2)}")
print(f"字典3的内容是:{my_dict3}, 类型:{type(my_dict3)}")
# 定义重复Key的字典
my_dict1 = {"王力宏": 99, "王力宏": 88, "林俊杰": 77}
print(f"重复key的字典的内容是:{my_dict1}")
# 从字典中基于Key获取Value
my_dict1 = {"王力宏": 99, "周杰伦": 88, "林俊杰": 77}
score = my_dict1["王力宏"]
print(f"王力宏的考试分数是:{score}")
score = my_dict1["周杰伦"]
print(f"周杰伦的考试分数是:{score}")
# 定义嵌套字典
stu_score_dict = {
"王力宏": {
"语文": 77,
"数学": 66,
"英语": 33
},
"周杰伦": {
"语文": 88,
"数学": 86,
"英语": 55
},
"林俊杰": {
"语文": 99,
"数学": 96,
"英语": 66
}
}
print(f"学生的考试信息是:{stu_score_dict}")
# 从嵌套字典中获取数据
# 看一下周杰伦的语文信息
score = stu_score_dict["周杰伦"]["语文"]
print(f"周杰伦的语文分数是:{score}")
score = stu_score_dict["林俊杰"]["英语"]
print(f"林俊杰的英语分数是:{score}")
4、字典的常用操作
(1)新增元素和更新元素
语法:字典[key]=Value,如果key之前存在就是更新元素,之前不存在就是新增元素
(2)删除元素
语法:字典.pop(key)
(3)清空元素
(4)获取全部的key
语法:字典.keys()
(5)遍历字典
方式1:获取全部的key
方式2:直接对字典进行for循环,每一次循环都直接得到key
(6)统计字典内的元素数量
"""
演示字典的常用操作
"""
my_dict = {"周杰伦": 99, "林俊杰": 88, "张学友": 77}
# 新增元素
my_dict["张信哲"] = 66
print(f"字典经过新增元素后,结果:{my_dict}")
# 更新元素
my_dict["周杰伦"] = 33
print(f"字典经过更新后,结果:{my_dict}")
# 删除元素
score = my_dict.pop("周杰伦")
print(f"字典中被移除了一个元素,结果:{my_dict},周杰伦的考试分数是:{score}")
# 清空元素,clear
my_dict.clear()
print(f"字典被清空了,内容是:{my_dict}")
# 获取全部的key
my_dict = {"周杰伦": 99, "林俊杰": 88, "张学友": 77}
keys = my_dict.keys()
print(f"字典的全部keys是:{keys}")
# 遍历字典
# 方式1:通过获取到全部的key来完成遍历
for key in keys:
print(f"字典的key是:{key}")
print(f"字典的value是:{my_dict[key]}")
# 方式2:直接对字典进行for循环,每一次循环都是直接得到key
for key in my_dict:
print(f"2字典的key是:{key}")
print(f"2字典的value是:{my_dict[key]}")
# 统计字典内的元素数量,len()函数
num = len(my_dict)
print(f"字典中的元素数量有:{num}个")
(7)字典课后小练习
"""
演示字典的课后练习:升职加薪,对所有级别为1级的员工,级别上升1级,薪水增加1000元
"""
# 组织字典记录数据
info_dict = {
"王力宏": {
"部门": "科技部",
"工资": 3000,
"级别": 1
},
"周杰伦": {
"部门": "市场部",
"工资": 5000,
"级别": 2
},
"林俊杰": {
"部门": "市场部",
"工资": 7000,
"级别": 3
},
"张学友": {
"部门": "科技部",
"工资": 4000,
"级别": 1
},
"刘德华": {
"部门": "市场部",
"工资": 6000,
"级别": 2
}
}
print(f"员工在升值加薪之前的结果:{info_dict}")
# for循环遍历字典
for name in info_dict:
# if条件判断符合条件员工
if info_dict[name]["级别"] == 1:
# 升职加薪操作
# 获取到员工的信息字典
employee_info_dict = info_dict[name]
# 修改员工的信息
employee_info_dict["级别"] = 2 # 级别+1
employee_info_dict["工资"] += 1000 # 工资+1000
# 将员工的信息更新回info_dict
info_dict[name] = employee_info_dict
# 输出结果
print(f"对员工进行升级加薪后的结果是:{info_dict}")
八、数据容器的通用统计方法
1、len(容器):元素个数
2、max(容器):最大元素
3、min(容器):最小元素
"""
演示数据容器的通用功能
"""
my_list = [1, 2, 3, 4, 5]
my_tuple = (1, 2, 3, 4, 5)
my_str = "abcdefg"
my_set = {1, 2, 3, 4, 5}
my_dict = {"key1": 1, "key2": 2, "key3": 3, "key4": 4, "key5": 5}
# len元素个数
print(f"列表 元素个数有:{len(my_list)}")
print(f"元组 元素个数有:{len(my_tuple)}")
print(f"字符串元素个数有:{len(my_str)}")
print(f"集合 元素个数有:{len(my_set)}")
print(f"字典 元素个数有:{len(my_dict)}")
# max最大元素
print(f"列表 最大的元素是:{max(my_list)}")
print(f"元组 最大的元素是:{max(my_tuple)}")
print(f"字符串最大的元素是:{max(my_str)}")
print(f"集合 最大的元素是:{max(my_set)}")
print(f"字典 最大的元素是:{max(my_dict)}")
# min最小元素
print(f"列表 最小的元素是:{min(my_list)}")
print(f"元组 最小的元素是:{min(my_tuple)}")
print(f"字符串最小的元素是:{min(my_str)}")
print(f"集合 最小的元素是:{min(my_set)}")
print(f"字典 最小的元素是:{min(my_dict)}")
4、list(容器):转换为列表
5、str(容器):转换为字符串
6、tuple(容器):转换为元组
7、set(容器):转换为集合
# 类型转换: 容器转列表
print(f"列表转列表的结果是:{list(my_list)}")
print(f"元组转列表的结果是:{list(my_tuple)}")
print(f"字符串转列表结果是:{list(my_str)}")
print(f"集合转列表的结果是:{list(my_set)}")
print(f"字典转列表的结果是:{list(my_dict)}")
# 类型转换: 容器转元组
print(f"列表转元组的结果是:{tuple(my_list)}")
print(f"元组转元组的结果是:{tuple(my_tuple)}")
print(f"字符串转元组结果是:{tuple(my_str)}")
print(f"集合转元组的结果是:{tuple(my_set)}")
print(f"字典转元组的结果是:{tuple(my_dict)}")
# 类型转换: 容器转字符串
print(f"列表转字符串的结果是:{str(my_list)}")
print(f"元组转字符串的结果是:{str(my_tuple)}")
print(f"字符串转字符串结果是:{str(my_str)}")
print(f"集合转字符串的结果是:{str(my_set)}")
print(f"字典转字符串的结果是:{str(my_dict)}")
# 类型转换: 容器转集合
print(f"列表转集合的结果是:{set(my_list)}")
print(f"元组转集合的结果是:{set(my_tuple)}")
print(f"字符串转集合结果是:{set(my_str)}")
print(f"集合转集合的结果是:{set(my_set)}")
print(f"字典转集合的结果是:{set(my_dict)}")
8、通用排序功能
sorted(容器,[reverse=Ture])
# 进行容器的排序
my_list = [3, 1, 2, 5, 4]
my_tuple = (3, 1, 2, 5, 4)
my_str = "bdcefga"
my_set = {3, 1, 2, 5, 4}
my_dict = {"key3": 1, "key1": 2, "key2": 3, "key5": 4, "key4": 5}
print(f"列表对象的排序结果:{sorted(my_list)}")
print(f"元组对象的排序结果:{sorted(my_tuple)}")
print(f"字符串对象的排序结果:{sorted(my_str)}")
print(f"集合对象的排序结果:{sorted(my_set)}")
print(f"字典对象的排序结果:{sorted(my_dict)}")
print(f"列表对象的反向排序结果:{sorted(my_list, reverse=True)}")
print(f"元组对象的反向排序结果:{sorted(my_tuple, reverse=True)}")
print(f"字符串对象反向的排序结果:{sorted(my_str, reverse=True)}")
print(f"集合对象的反向排序结果:{sorted(my_set, reverse=True)}")
print(f"字典对象的反向排序结果:{sorted(my_dict, reverse=True)}")
九、函数进阶
1、函数的多返回值
如果一个函数要有多个返回值,该如何书写代码?
按照返回值的顺序,写对应顺序的多个变量接收即可
变量之间用逗号隔开
支持不同类型的数据return
def test_return():
return 1, 2
x, y = test_return()
print(x) # 结果1
print(y) # 结果2
2、函数的参数
(1)函数的参数种类
位置参数、关键字参数、缺省参数、不定长参数
(2)位置参数:调用函数时根据函数定义的参数位置来传递参数
注意:
传递的参数和定义的参数的顺序及个数必须一致
def user_info(name, age, gender):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('Tom', 20, '男')
(3)关键字参数:函数调用时通过“键=值”形式传递参数.
作用:可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求.
注意:
函数调用时,如果有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
def user_info(name, age, gender):
print(f"您的名字是:{name},年龄是:{age},性别是:{gender}")
# 关键字传参
user_info(name="小明", age=20, gender="男")
# 可以不按照固定顺序
user_info(age=20, gender="男", name="小明")
# 可以和位置参数混用,位置参数必须在前,且匹配参数顺序
user_info("小明", age=20, gender="男")
(4)缺省参数:缺省参数也叫默认参数,用于定义函数,为参数提供默认值,调用函数时可不传该默认参数的值(注意:所有位置参数必须出现在默认参数前,包括函数定义和调用).
作用:当调用函数时没有传递参数,就会使用默认是用缺省参数对应的值.
注意:
函数调用时,如果为缺省参数传值则修改默认参数值,否则使用这个默认值
def user_info(name, age, gender='男'):
print(f'您的名字是{name},年龄是{age},性别是{gender}')
user_info('TOM', 20)
user_info('Rose', 18, '女')
(5)不定长参数:不定长参数也叫可变参数,用于不确定调用的时候会传递多少个参数(不传参也可以)的场景.
作用:当调用函数时不确定参数个数时,可以使用不定长参数
不定长参数的类型:
①位置传递
②关键字传递
位置传递
注意:
传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
def user_info(*args):
print(args)
user_info('TOM')
user_info('TOM', 18)
关键字传递
注意:
参数是“键=值”形式的情况下,所有的“键=值”都会被kwargs接受,同时会根据“键=值”组成字典.
def user_info(**kwargs):
print(kwargs)
user_info(name='TOM', age=18, id=110)
3、函数作为参数传递
计算逻辑的传递,非数据的传递
def test_func(compute):
result = compute(1, 2)
print(result)
def compute(x, y):
return x + y
test_func(compute)
函数compute,作为参数,传入了test_func函数中使用。
• test_func需要一个函数作为参数传入,这个函数需要接收2个数字进行计算,计算逻辑由这个被传入函数决定
• compute函数接收2个数字对其进行计算,compute函数作为参数,传递给了test_func函数使用
• 最终,在test_func函数内部,由传入的compute函数,完成了对数字的计算操作
4、匿名函数
lambda匿名函数
(1)函数的定义中
• def关键字,可以定义带有名称的函数
• lambda关键字,可以定义匿名函数(无名称)
有名称的函数,可以基于名称重复使用。
无名称的匿名函数,只可临时使用一次。
(2)匿名函数定义语法:
lambda 传入参数:函数体(一行代码)
• lambda是关键字,表示定义匿名函数
• 传入参数表示匿名函数的形式参数,如:x, y表示接收2个形式参数
• 函数体,就是函数的执行逻辑,要注意:只能写一行,无法写多行代码
def test_func(compute):
result = compute(1, 2)
print(result)
test_func(lambda x, y: x + y)
可以通过lambda关键字,传入一个一次性使用的lambda匿名函数
使用def和使用lambda,定义的函数功能完全一致,只是lambda关键字定义的函数是匿名的,无法二次使用