【python高级用法】迭代器、生成器、装饰器、闭包

迭代器

  • 可迭代对象:可以使用for循环来遍历的,可以使用isinstance()来测试。

  • 迭代器:同时实现了__iter__()方法和__next__()方法,可以使用isinstance()方法来测试是否是迭代器对象


from collections.abc import Iterable, Iterator
li = [11, 22, 33, 44, 55]print(isinstance(li, Iterable)
iterator_li = iter(li)
print(isinstance(iterator_li, Iterator)

使用类实现迭代器

两个类实现一个迭代器


class MyList(object):"""自定义的一个可迭代对象"""def __init__(self):self.items = []def add(self, val):self.items.append(val)def __iter__(self):#python中万物皆对象,将该类对象的引用self作为实参传入到MyIterator类中myiterator = MyIterator(self)return myiteratorclass MyIterator(object):"""自定义的供上面可迭代对象使用的一个迭代器"""#这里的mylist就MyList对象def __init__(self, mylist):self.mylist = mylist# current用来记录当前访问到的位置#每一次调用for循环时,索引位置都从零开始self.current = 0def __next__(self):if self.current < len(self.mylist.items):item = self.mylist.items[self.current]self.current += 1return itemelse:raise StopIterationdef __iter__(self):return self

一个类实现迭代器


class MyList(object):"""自定义的一个可迭代对象"""def __init__(self):self.items = []self.current = 0def add(self, val):self.items.append(val)def __iter__(self):#返回自身引用,自己本身就是一个迭代器对象return selfdef __next__(self):if self.current < len(self.items):item = self.items[self.current]self.current += 1return itemelse:#使用for循环第二次遍历时,self.current可以从0开始self.current = 0raise StopIteration
  • 可迭代对象与迭代器的总结

  1. 一个具备了__iter__方法的对象,就是一个可迭代对象

  1. 当对一个可迭代对象调用iter()函数时,它会自动调用这个可迭代对象的__iter__方法,这个方法返回的对象当作迭代器

  1. 当对一个迭代器对象调用next()函数时,他会自动调用这个迭代器对象的__next__方法,这个方法返回想要的数据

  1. 迭代器一定是可迭代对象,可迭代对象不一定是迭代器

  1. 数据类型list、dict、str等是Iterable单不是Iterator,不过可以通过iter()函数获得一个Iterator对象

  • 迭代器的应用

  1. 如果每次返回的数据值不是在一个已有的数据集合中,而是通过程序按照一定的规律计算生成的,那就不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来,这样可以节省大量的存储(内存)空间。


class FeiboIterator(object):"""斐波那契数列迭代器"""def __init__(self, n):# 斐波那数列值的个数self.n = n# 记录当前遍历的下标self.index = 0# 斐波那数列前面的两个值self.num1 = 0self.num2 = 1def __next__(self):"""被next()函数调用来获取下一个数"""if self.index < self.n:num = self.num1self.num1, self.num2 = self.num2, self.num1 + self.num2self.index += 1return numelse:raise StopIterationdef __iter__(self):"""迭代器的__iter__返回自身即可"""return selfif __name__ == '__main__':fb = FeiboIterator(20)for num in fb:print(num, end=' ')

生成器

生成器的定义

  1. 使用了yield关键字的函数不再是函数,而是生成器。

  1. yield关键字有两点作用:

  • 保存当前运行状态(断点),然后暂停执行,即将生成器(函数)挂起

  • 将yield关键字后面表达式的值作为返回值返回,此时可以理解为起到了return作用

  1. 可以使用next()函数让生成器从断点处继续执行,唤醒生成器(函数)

  1. python3中的生成器可以使用return返回最终运行的返回值

  1. 生成器是这样一个函数,他记住上一次返回在函数体中的位置。对生成器函数的第二次(或第n次)调用跳转至函数中间,而上次调用的所有的局部变量都保持不变。生成器不仅记住了他的数据状态,生成器还记住了它在流程控制构造(在命令式编程中,这种构造不只是数据值)中的位置。

  1. 生成器的特点:

  • 存储的是生成数据的方式(即算法),而不是存储生成的数据,因此节约内存。

生成器的使用


def create_points():k = 2b = 1x = 0while True:y = k * x + b#当使用send方法时,会将send方法中的参数赋给temp,send()方法与next()方法类似,都可以取生成器中的下一个元素。temp = yield (x,y)if temp:k, b = tempx = yif __name__ == '__main__':#不再是一个普通函数的调用,因为函数体内包含yield关键字,此时是生成一个生成器对象g = create_points()# print(next(g))# print(next(g))# print(g.send((3, 4)))# print(next(g))# print(next(g))count = 0for i in g:if count > 3:breakprint(i)count += 1

参考链接:

python生成器的原理和业务场景下的使用_for line in tqdm(f, desc='read sentence_cuts'):如果不-CSDN博客

装饰器

装饰器的定义

装饰器可以在不改变某函数结构和调用方式基础之上,为其增加新的功能,并且最大化复用新的功能。

装饰器的应用场景

为函数增加日志记录、登录校验、权限校验等,我们可以将这些功能写成一个装饰器,然后直接应用到相应需要改功能的函数中即可,可以保证对原代码和函数零侵入。

装饰器的本质是一个闭包函数

  • 装饰器函数
def timing_decorator(func):def wrapper(*args, **kwargs):start_time = time.time()result = func(*args, **kwargs)end_time = time.time()execution_time = end_time - start_timeprint(f"{func.__name__} cost time: {execution_time:.4f} s")return resultreturn wrapper
  • 构造执行函数
@timing_decorator
def demo():time.sleep(5)

执行demo函数时,会打印该函数执行时间为5s

参考文献:

python装饰器全解--包含实现原理及应用场景_装饰器实现原理-CSDN博客

闭包

什么是闭包

概念:一个函数可以引用作用域外的变量,同时也可以在函数内部进行使用的函数,称之为闭包函数。而这个作用域外的变量,称之为自由变量。这个自由变量不同于C++的static修饰的静态变量,也不同于全局变量,它是和闭包函数进行绑定的。

  1. 闭包函数是函数的嵌套,函数内还有函数,即外层函数嵌套一个内层函数

  1. 在外层函数定义局部变量,在内层函数通过nonlocal引用,并实现指定功能,比如计数

  1. 最后外层函数return内层函数

  1. 主要作用:可以变相实现私有变量的功能,即用内层函数访问外层函数内的变量,并让外层函数内的变量常驻内存

为什么要使用闭包

  1. 封装变量: 闭包允许你创建一个包含函数和其所在环境中变量的封闭空间。这样,你可以隐藏一些变量,使其不易被外部访问,起到一定的封装作用。

  2. 保持状态: 闭包函数可以保持其创建时的状态。这意味着你可以在函数外部改变闭包内部的变量,并且在多次调用闭包时保持这些变量的状态。

  3. 函数工厂: 闭包函数可以用作函数工厂,动态生成函数。这对于根据不同情况生成不同行为的场景很有用。

  4. 实现装饰器: 闭包函数常用于实现装饰器模式,通过在函数外层包装其他函数来增强其功能,而无需修改原始函数的代码。

  5. 实现私有变量和方法: 通过闭包,你可以模拟出类似于面向对象编程中的私有变量和方法,限制对内部实现的访问。

闭包的应用场景是什么

创建一个计数器,但又不想让外部直接访问计数变量

def create_counter():count = 0  # 这个变量在闭包内def counter():nonlocal count  # 使用 nonlocal 关键字声明 count 不是局部变量count += 1return countreturn counter# 创建一个计数器
my_counter = create_counter()# 使用计数器
print(my_counter())  # 输出 1
print(my_counter())  # 输出 2
print(my_counter())  # 输出 3

在这个例子中,create_counter 函数返回了一个内部定义的 counter 函数count 变量被封装在 counter 函数的闭包中,因此外部无法直接访问。每次调用 my_counter() 时,计数器会递增并返回当前计数值。

这样做的好处是,我们可以创建多个独立的计数器,它们各自维护自己的状态,而不会互相干扰。闭包在这里提供了一种轻量级的状态封装和隔离的机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/228144.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kivy中用anchrolayout

说明 AnchorLayout 是 Kivy 框架中用于管理界面元素位置的一种布局方式。AnchorLayout 的特点是&#xff0c;它可以将其子元素锚定到布局的边界上&#xff0c;例如顶部、底部、左侧或右侧。这使得在需要元素相对于其容器边界保持固定位置时非常有用。 界面 # mylayout.kvAnch…

Android : 画布的使用 简单应用

示例图&#xff1a; MyView.java&#xff1a; package com.example.demo;import android.content.Context; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.view.Vi…

JVM高频面试题(2023最新版)

JVM面试题 1、JVM内存区域 Jvm包含两个子系统和两个组件。 1.1子系统 Class loader&#xff08;类加载器&#xff09;&#xff1a;根据给定的全限定名类名&#xff08;java.lang.object&#xff09;来装载class文件到Runtime data area&#xff08;运行时数据区&#xff09;…

移动端开发框架mui代码在安卓模拟器上运行2(HbuilderX连接到模拟器)模拟器窗口及多开设置

开发工具 HBuilder X 3.8.12.20230817 注意&#xff1a;开发工具尽量用最新的或较新的。太旧的版本在开发调试过程中可能会出现莫名其妙的问题。 接上篇&#xff0c;移动端开发框架mui代码在安卓模拟器上运行&#xff08;HbuilderX连接到模拟器&#xff09;&#xff0c;这篇主要…

SkyWalking UI 修改发布Nginx

文章目录 SkyWalking UI修改图标修改路由发布到Nginx添加认证修改路由模式vite.config.ts添加baseNginx配置 SkyWalking UI skywalking-booster-ui下载地址 修改图标 替换 logo.svg 修改路由 router - data - index.ts 发布到Nginx 添加认证 # 安装 yum install -y h…

【STM32】STM32学习笔记-PWM驱动LED呼吸灯 舵机 直流电机(16)

00. 目录 文章目录 00. 目录01. 输出比较相关API1.1 TIM_OC1Init1.2 TIM_OCInitTypeDef结构体1.3 TIM_OCMode1.4 TIM_OutputState1.5 TIM_OutputNState1.6 TIM_OCPolarity1.7 TIM_OCNPolarity1.8 TIM_OCPolarity1.9 TIM_OCNPolarity 02. PWM实现呼吸灯接线图03. PWM实现呼吸灯示…

SetWindowsHookEx: 全局钩子实现键盘记录器

简介 SetWindowsHookEx 钩子(Hook)&#xff0c;是Windows消息处理机制的一个平台&#xff0c;应用程序可以在上面设置子程以监视指定窗口的某种消息&#xff0c;而且所监视的窗口可以是其他进程所创建的。当消息到达后&#xff0c;在目标窗口处理函数之前处理它。钩子机制允许应…

【后端】Docker学习笔记

文章目录 Docker一、Docker安装&#xff08;Linux&#xff09;二、Docker概念三、Docker常用命令四、数据卷五、自定义镜像六、网络七、DockerCompose Docker Docker是一个开源平台&#xff0c;主要基于Go语言构建&#xff0c;它使开发者能够将应用程序及其依赖项打包到一个轻…

idea构建maven项目报错的解决

使用idea创建了一个新的spring项目&#xff0c;maven配置完毕后&#xff0c;报错&#xff0c;引用的依赖不存在。 控制台报错信息如下&#xff1a; 通过查询资料&#xff0c;发现是阿里云的maven仓库中没有这个版本的jar包&#xff0c;导入无法引用到对应的依赖。 解决方法就是…

go的json数据类型处理

json对象转slice package mainimport ("encoding/json""fmt""github.com/gogf/gf/container/garray" )func main() {// JSON 字符串jsonStr : ["apple", "banana", "orange"]//方法一&#xff1a;// 解析 JSON 字…

HTML-基础知识-基本结构,注释,文档说明,字符编码(一)

1.超文本标记语言不分大小写。 2.超文本标签属性名和属性值不区分大小写。 3.超文本标签属性值重复&#xff0c;听取第一个。 4.html结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"vi…

单片机的存储、堆栈与程序执行方式

一、单片机存储区域 如图所示位STM32F103ZET6的参数&#xff1a; 单片机的ROM&#xff08;内部FLASH&#xff09;&#xff1a;512KB&#xff0c;用来存放程序代码的空间。 单片机的RAM&#xff1a;64KB&#xff0c;一般都被分配为堆、栈、变量等的空间。 二、堆和栈的概念 …

关于“Python”的核心知识点整理大全53

目录 18.2.7 Django shell 注意 18.3 创建网页&#xff1a;学习笔记主页 18.3.1 映射 URL urls.py urls.py 注意 18.3.2 编写视图 views.py 18.3.3 编写模板 index.html 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xff1a; 感谢大家的支…

FPGA - 231227 - 5CSEMA5F31C6 - 电子万年历

TAG - F P G A 、 5 C S E M A 5 F 31 C 6 、电子万年历、 V e r i l o g FPGA、5CSEMA5F31C6、电子万年历、Verilog FPGA、5CSEMA5F31C6、电子万年历、Verilog 顶层模块 module TOP(input CLK,RST,inA,inB,inC,switch_alarm,output led,beep_led,output [41:0] dp );// 按键…

<JavaEE> TCP 的通信机制(一) -- 确认应答 和 超时重传

目录 TCP的通信机制的核心特性 一、确认应答 1&#xff09;什么是确认应答&#xff1f; 2&#xff09;如何“确认”&#xff1f; 3&#xff09;如何“应答”&#xff1f; 二、超时重传 1&#xff09;丢包的概念 2&#xff09;什么是超时重传&#xff1f; 3&#xff09…

【VMware】Windows安装MySQL(5.78版本)及网络配置---图文并茂详细介绍

一 安装MySQL准备工作 ① 连接虚拟机传输MySQL压缩包 先查看虚拟机中的地址 命令&#xff1a; ipconfig 主机连接 在主机连接虚拟机后&#xff0c;将mysql压缩包和Navicat安装包复制到虚拟机下即可 ②解压MySQL压缩包 ③ my文件拷贝mysql安装根目录下 如下图的第一步&…

vue-springboot基于JavaWeb的家装一体化商城平台guptn

针对用户需求开发与设计&#xff0c;该技术尤其在各行业领域发挥了巨大的作用&#xff0c;有效地促进了家装一体化的发展。然而&#xff0c;由于用户量和需求量的增加&#xff0c;信息过载等问题暴露出来&#xff0c;为改善传统线下管理中的不足&#xff0c;本文将提出一套基于…

IntelliJ IDEA常用快捷键

【1】创建内容&#xff08;新建&#xff09;&#xff1a;altinsert 【2】main方法&#xff1a;psvm 【3】输出语句&#xff1a;sout 【4】复制行&#xff1a;ctrld 【5】删除行&#xff1a;ctrly&#xff08;很多编辑器ctrly是前进操作&#xff0c;如果选择 Delete Line&…

Apollo自动驾驶:改变交通运输的游戏规则

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言1. Apollo缓存层2. 本地状态管理库3. 离线同步和冲突解决4. 离线数据同步和离线优先策略结论 &#x1f4f2;&#x1f50c; 构建离线应用&#xff1a;Apollo…

磁盘和文件系统管理

一&#xff1a;磁盘结构&#xff1a; 1.磁盘基础&#xff1a; 扇区固定大小&#xff0c;每个扇区4k。磁盘会进行磨损&#xff0c;损失生命周期。 设备文件&#xff1a; 一切皆文件 设备文件&#xff1a;关联至一个设备驱动程序&#xff0c;进而能够跟与之对应硬件设备进行通…