【测试开发学习历程】python迭代、可迭代对象、迭代器、生成器

news/2024/5/22 2:49:37/文章来源:https://blog.csdn.net/Sodagreen_yyds/article/details/137535400

1 迭代Iteration

迭代Iteration:所谓迭代就是重复运行一段代码语句块的能力,就好比在一个容器中进行一层一层遍历数据,在应用过程中for循环最为突出。迭代就是从某个容器对象中逐个地读取元素,直到容器中没有元素为止。迭代迭代,更新换代,在上一次基础上更新成新的东西。

# 使用for循环迭代这个字符串,其实就是我们说的遍历这个字符串
for i in "hello world":print(i)

2 可迭代对象Iterable

2.1 什么是可迭代对象

可迭代对象Iterable:可以被迭代的类型,怎么判断是否可迭代?

所有的类型只要有__iter__()方法就是可迭代的。我们现在已知的可迭代对象有:str,list,tuple,range,set,dict_keys,dict_values,dict_items

方法名前后有两个下划线的,也叫魔法方法。

2.2 怎么判断可迭代对象

怎么去判断某个对象是否有__iter__()方法?

  1. dir()函数来查询是否包含__iter__()方法;

  2. 通过对象.方法的方式去调用看有没有__iter__方法;

  3. 通过内置的实例对象函数isinstance()判断,可迭代对象是Iterable类的实例,返回True就说明是可迭代对象,False则表示不是可迭代对象。isinstance()函数格式:isinstance(object, class)

# 用dir()函数打印数据的全部方法,看看是否包含__iter__()方法
print(dir(list1))
​
# 查看某个元素或序列是否有.__iter__()方法,有就是可迭代的对象
"hello world".__iter__()
[2].__iter__()
(1,).__iter__()
{"name":"jack"}.__iter__()
{"name":"jack"}.keys().__iter__()
range(11).__iter__()
list1=[]
a=9
​
# 通过内置的实例对象函数isinstance()判断
from collections.abc import Iterable,Iterator
print(isinstance(list1,Iterable))   # 结果是True
print(isinstance(a,Iterable))       # 结果是False

3 迭代器Iterator

3.1 什么是迭代器

  • 迭代器Iterator:迭代器一定是可迭代对象,迭代器中有两个特殊的方法是__iter__()__next__()方法

  • 创建迭代器的方法:使用内置的iter()函数或者__iter__()方法来创建迭代器

  • 举例:

    # 将列表转换为迭代器
    list1=[1,3,5,7,9]
    it1=iter(list1)
    it2=list1.__iter__()
    print(type(it1))
    print(type(it2))
    ​
    # 打印迭代器中的数据,每次只能打印一个元素,有多少元素就需要打印多少次
    # 用next()函数取迭代器中的数据
    print(next(it1)) 
    # 用__next__()方法取迭代器中的数据
    print(it1.__next__()) 
    print(it1.__next__())
    print(it1.__next__())
    print(it1.__next__())
    # print(it1.__next__())
    # print(it1.__next__())

  • 可迭代对象与迭代器关系示意图:

    举例:a = iter([4, 3, 6, 8])

  • 迭代器的特点是:

    1. 迭代器一定是可迭代对象;

    2. 迭代器通过next()函数或者__next__()方法取值,每迭代一次取一个值,只能往前取不能后退;

    3. 当取完最后一个值的时候,再执行next()函数或者__next__()方法会报StopIteration异常,表示取完了。

3.2 怎么判断迭代器

判断一个对象是迭代器还是迭代对象,可以使用以下两种方法:

  1. 通过对象包含__iter__()__next__()方法来判断;

  2. 需要判断是迭代器还是迭代对象,可以通过实例对象函数isinstance()进行判断,迭代器和可迭代对象的对象类型分别是IteratorIterable(都是collections.abc模块下)

from collections.abc import Iterator,Iterable
# Iterator是判断是否是迭代器
# Iterable是判断是否是可迭代对象
print(isinstance(list1,Iterable))               #判断list1是否是可迭代对象返回True或False
print(isinstance(list1,Iterator))               #判断list1是否是迭代器返回True或False
print(isinstance(iter(list1),Iterator))         #True
print(isinstance(it1,Iterable))                 #True
print(isinstance(it1,Iterator))                 #True
​
#计算1+2+3+...+1000000000
#print(sum(list(range(1,1000000001))))
#print(sum(iter(range(1,1000000001))))

迭代器的优缺点:

  1. 迭代器优点:节省内存,迭代器在内存中相当于只占一个数据的空间,因为每次取值都会把上一条数据在内存中释放,加载当前的此条数据。

  2. 迭代器的缺点,不能直观的查看里面的数据。取值时不走回头路,只能一直向下取值。

3.3 for循环的底层原理

for循环实现遍历的底层原理:(for循环将其都封装好了,所以for循环in后面必须跟的是可迭代对象

  1. for循环可以传入可迭代对象或者迭代器对象,在循环的时候先调用可迭代对象的iter()函数来生成迭代器;

  2. 调用迭代器的next()函数来迭代每个元素;

  3. 当迭代完最后一个元素时,再继续迭代会报StopIteration异常,for循环捕捉到这个异常就知道已经迭代完了,就结束循环。

for循环的实现原理:

也可以用for循环去遍历迭代器。

4 生成器Generator

4.1 什么是生成器

生成器Generator:在 Python 中,生成器的本质就是一个迭代器,使用了yield 的函数被称为生成器(generator)。

4.2 生成器怎么创建

创建生成器的方法:

  • 方法一:

  1. 第一步:定义一个包含yield语句的函数

  2. 第二步:调用第一步创建的函数得到一个生成器

# 例1:使用yield关键字把函数变成装饰器
def generator_1():yield 1# 创建生成器,如下表示创建一个生成器,赋值给gen
gen=generator_1()
print(type(gen))
​
# 在函数中可以使用多个yield
def generator_2():yield 1yield 2yield 3# 也可以一个yield语句返回多个值,跟使用return类似,此时将返回一个元组
def generator_3():yield 1, 2
  • 方法二:使用生成器推导式来创建生成器

# 例2:通过生成器推导式创建生成器
print(type((i for i in range(11))))
print((i for i in range(11)))#是一个生成器对象

4.3 return与yield的区别

return的作用:

  1. 给调用者返回值;

  2. 执行遇到第一个return语句时就结束函数。

yield的作用:

  1. 给调用者返回值;

  2. yield把函数变成了生成器;

  3. 生成器运行时遇到yield后先返回再挂起;

  4. 在函数中可以使用多个yield。

4.4 生成器的运行

带有 yield 的函数执行过程比较特别:

  1. 调用该函数的时候不会立即执行代码,而是返回了一个生成器对象;

  2. 当使用next()函数或者__next__()方法作用于返回的生成器对象时,函数开始执行,在遇到 yield 的时候会『暂停』,并返回当前的迭代值; 也可以使用for循环来迭代生成器对象,因为在for循环中会自动调用next()函数;

  3. 当再次使用 next() 的时候,函数会从原来『暂停』的地方继续执行,直到遇到 yield语句,如果没有 yield 语句,则抛出异常;

整个过程看起来就是不断地 执行->中断->执行->中断 的过程。一开始,调用生成器函数的时候,函数不会立即执行,而是返回一个生成器对象;然后,当我们使用 next() 作用于它的时候,它开始执行,遇到 yield 语句的时候,执行被中断,并返回当前的迭代值,要注意的是,此刻会记住中断的位置和所有的变量值,也就是执行时的上下文环境被保留起来;当再次使用 next() 的时候,从原来中断的地方继续执行,直至遇到 yield,如果没有 yield,则抛出异常。简而言之,就是 next() 使函数执行, yield 使函数暂停。

# 在定义函数时,使用yield来返回值
def generator_1():yield 1yield 2yield 3
​
# 直接这个函数的调用结果,得不到返回的值
print(generator_1())
​
# 使用next()函数或者__next__()方法来运行该函数,但如下每次执行时都返回第一个值,因为每次调用的时候都会创建一个生成器
print(next(generator_1()))
print(next(generator_1()))
print(generator_1().__next__())
​
# 可以调用一次函数,对返回结果赋值给一个变量,这样可以获取生成器所有返回的值
def generator_1():yield 1yield 2yield 3
# 调用函数,返回一个生成器对象,赋值给变量gt
gt=generator_1()
# 通过next()函数来执行这个生成器对象
print(next(gt))
print(next(gt))
​
# 使用for循环执行生成器
for i in gt:print(i)

4.5 send()方法

通过send()方法也可以执行生成器,同时可以向生成器传入值。

send()方法与next()函数的区别:

  1. send()方法与next()函数都用来执行生成器;

  2. send()方法会将传入的值赋给上次中断时yield语句的执行结果,然后再执行生成器,从而实现与生成器方法的交互;

  3. 在执行生成器时,如果第一次执行使用send()方法,因为没有挂起的yield语句来接收传入的值,所以会报TypeError异常。

  4. 简单地说, send() 方法就是 next() 函数的功能,加上传值给 yield 。

# 例1:第一次使用send()方法执行生成器
def generator_1():yield 1yield 2yield 3gt1=generator_1()
# 如下代码会报错,因为第一次需要先使用next()函数来执行生成器
print(gt1.send(100))
print(gt1.send(200))
​
# 例2:第一次使用next()执行生成器,第二次开始使用send()执行生成器并传入值
def generator_2():a=yield 1b=yield ayield bc=yield 2print(c)yield c
​
gt2=generator_2()
# 首先使用next()函数执行生成器,返回1之后挂起
print(next(gt2))
# 使用send()方法传入100给yield 1的执行结果,也就是a,然后再执行yield a,返回100,再挂起
print(gt2.send(100))
# 使用send()方法传入2.5给yield a的执行结果,也就是b,然后再执行yield b,返回2.5,再挂起
print(gt2.send(2.5))
# 使用send()方法传入'abc'给yield b的执行结果,但并没有引用他,然后执行yield 2,返回2,再挂起
print(gt2.send('abc'))
# 传入efg给yield 2的执行结果,也就是c,然后再打印c,最后再执行yield c,返回efg
print(gt2.send('efg'))

4.6 生成器与迭代器的区别

  • 生成器:

    1. 生成器本身是一种特殊的迭代器,也就是说生成器就是迭代器。

    2. 生成器会自动实现迭代器协议,也就是说只要我们yield后,自动就生成了next对象包括StopIteration等结构。

    3. 生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。生成器不仅“记住”了它的数据状态,生成还记住了程序执行的位置。

  • 迭代器:

    1. 迭代器是一种支持next()操作的对象。它包含了一组元素,当执行next()操作时,返回其中一个元素;

    2. 当所有元素都被返回后,再执行next()报异常StopIteration

    3. 生成器一定是可迭代的,也一定是迭代器对象。

  • 它们的区别:

  1. 迭代器是访问容器的一种方式,也就是说容器已经出现。我们是从已有元素拓印出一份副本,只为我们此次迭代使用。而生成器则是自己生成元素的。也就是前者是从有到有的复制,而后者则是从无到有的生成。

  2. 在用法上生成器只需要简单函数写法,配合yield就能实现。而迭代器真正开发中很难使用到。我们可以把生成器看做,python给我们提供的特殊接口实现的迭代器。

最后,附上一张图来解释容器、可迭代对象、迭代器、生成器之间的关系:

4.7 生成器使用举例:处理大量数据

生成器的优势在于在没有牺牲很多的速度情况下,内存占用更小,在一定的业务场景下,支持大数据的操作。

举例:通过列表和生成器分别处理1亿条数据对比

# 通过列表实现,如下代码在执行时可观察电脑的内存使用情况,内存会被占满
a = []
for i in range(100000000):temp = ['你好']*2000a.append(temp)
​
[[你好,你好,...,你好],[你好,你好,...,你好],...,[你好,你好,...,你好]]
for ele in a:# print(ele)continue
​
# 通过生成器实现,如下代码在执行时可观察电脑的内存使用情况,内存占用不大
def get_list_element():for i in range(100000000):temp = ['你好']*2000yield temp
# 创建一个生成器
a = get_list_element()
for ele in a:# print(ele)continue

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

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

相关文章

信息泄露漏洞的JS整改方案

引言 🛡️ 日常工作中,我们经常会面临线上环境被第三方安全厂商扫描出JS信息泄露漏洞的情况,这给我们的系统安全带来了潜在威胁。但幸运的是,对于这类漏洞的整改并不复杂。本文将介绍几种可行的整改方法,以及其中一种…

IPEX-LLM(原名BigDL-LLM)环境配置

IPEX-LLM 是一个为Intel XPU (包括CPU和GPU) 打造的轻量级大语言模型加速库,在Intel平台上具有广泛的模型支持、最低的延迟和最小的内存占用。 您可以使用 IPEX-LLM 运行任何 PyTorch 模型(例如 HuggingFace transformers 模型)。在运行过程中…

Canal的使用场景!!!

1、保持redis和mysql连接的一致性:通常使用延迟双删功能(具有弊端) 解决方案:可以使用canal监听数据库的变化(删改),一旦出现此类操作,立即删除redis中的对应数据,直至下…

SuperMap GIS基础产品FAQ集锦(202403)

一、SuperMap GIS基础产品桌面GIS-FAQ集锦 问题1:【iDesktop】安装了idesktop 11i,现想进行插件开发,根据安装指南安装SuperMap.Tools.RegisterTemplate.exe,运行多次均失败 【问题原因】该脚本是之前老版本针对VS2010写的&…

AOF文件重写

1.2.3.AOF文件重写 因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。 如图&am…

穿越代码之海:探寻结构体深层逻辑,展望未来应用新天地

欢迎来到白刘的领域 Miracle_86.-CSDN博客 系列专栏 C语言知识 先赞后看,已成习惯 创作不易,多多支持! 结构体作为一种数据结构,其定义和特点决定了它在各种应用中的广泛适用性。随着科技的进步和新兴行业的不断涌现&#xf…

C语言—每日选择题—Day68

第一题 1、运行以下C语言代码&#xff0c;输出的结果是&#xff08;&#xff09; #include <stdio.h> int main() {char *str[3] {"stra", "strb", "strc"};char *p str[0];int i 0;while(i < 3){printf("%s ",p);i;} retur…

【Gem5】获取构建教程

gem5-tutorial-hpca-2023 1 介绍 1.1 Gem5是什么1.2 Gem5可以用来做什么1.3 获取并构建gem5 gem5-tutorial-hpca-2023 打开网址&#xff1a; github 创建教程代码空空间 “Code” -> “Codespaces” -> “Create Codespace on master” GitHub Codespaces 是一个由…

Java Swing游戏开发学习23

内容来自RyiSnow视频讲解 这一节讲的是Character Status角色状态或属性。 前言 这一节讲的是实现角色状态或属性的显示&#xff0c;就有点像RPG游戏中&#xff0c;人物属性显示的面板&#xff0c;其中有玩家的装备、玩家的等级&#xff0c;各种防御值、闪避值、跑速什么的。…

探索进程控制第一弹(进程终止、进程等待)

文章目录 进程创建初识fork函数fork函数返回值fork常规用法fork调用失败的原因 写时拷贝进程终止进程终止是在做什么&#xff1f;进程终止的情况代码跑完&#xff0c;结果正确/不正确代码异常终止 如何终止 进程等待概述进程等待方法wait方法waitpid 进程创建 初识fork函数 在…

Vue3_2024_7天【回顾上篇watch常见的后两种场景】___续

Vue3中监听多条数据的两种使用 1.watch【使用上一章写法&#xff0c;监听两个属性&#xff0c;然后执行相应操作…】 2.watchEffect【相对于使用watch&#xff0c;watchEffect默认页面初始加载&#xff0c;有点类似加配置&#xff1a;立即执行 immediate】 代码&#xff1a; …

单链表专题

文章目录 目录1. 链表的概念及结构2. 实现单链表2.1 链表的打印2.2 链表的尾插2.3 链表的头插2.4 链表的尾删2.5 链表的头删2.6 查找2.7 在指定位置之前插入数据2.8 在指定位置之后插入数据2.9 删除pos节点2.10 删除pos之后的节点2.11 销毁链表 3. 链表的分类 目录 链表的概念…

Qt小案例

工程概述 MainWindows 还是 Widget 在 Qt 中&#xff0c;创建 "MainWindow" 与 "Widget" 项目的主要区别在于他们的用途和功能范围&#xff1a; 1. MainWindow &#xff1a;这是一个包含完整菜单栏、工具栏和状态栏的主窗口应用程序框架。它适合于更…

python画图Matplotlib和Seaborn

python画图Matplotlib和Season 一、Matplotlib1、介绍2、安装3、内容二、Seaborn1、介绍2、安装3、内容一、Matplotlib Matplotlib官网 1、介绍 Matplotlib 是一个 Python 的绘图库,用于创建高质量的二维图表和一些基本的三维图表。它广泛应用于科学计算、数据分析、工程学和…

泛微OA 自定义多选浏览框

1、建模引擎-》应用建模-》表单 2、建模引擎-》应用建模-》模块 3、建模引擎-》应用建模-》查询 4、把查询页面挂到前端页面。 效果展示&#xff1a; 5、建模引擎-》应用建模-》浏览框 6、流程表单中字段应用

IP-GUARD内置用户系统同步飞书组织架构使用说明

一、功能简介 实现将飞书的通讯录组织架构同步到内置用户系统。 二、功能配置 2.1 飞书创建自建应用 在浏览器上打开飞书开放平台 https://open.feishu.cn ,登录管理员账号后点击开发 者后台 在开发者后台点击创建企业自建应用,填写自建应用程序名称以及描述,设置图标,点…

SSRF靶场

SSRF概述 ​ 强制服务器发送一个攻击者的请求 ​ 互联网上的很多web应用提供了从其他服务器&#xff08;也可以是本地)获取数据的功能。使用用户指定的URL&#xff0c;web应用可以获取图片&#xff08;载入图片&#xff09;、文件资源&#xff08;下载或读取)。如下图所示&…

利用Leaflet + React:构建WEBGIS

React是 Facebook 开发的一个开源库&#xff0c;用于构建用户界面。就其本身而言&#xff0c;Leaflet是一个用于将地图发布到网络的JavaScript 库。这两个工具的组合很简单&#xff0c;允许您创建动态网络地图。在本文中&#xff0c;我们将看到这种组合的一些特征以及一些简单的…

【MySQL数据库 | 第二十五篇】深入探讨MVCC底层原理

前言&#xff1a; 在当今互联网时代&#xff0c;数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言&#xff0c;高效地处理并发访问和事务管理是至关重要的。多版本并发控制&#xff08;MVCC&#xff09;是一种数据库事务处理的技术&#xff0c;旨…

三种常见webshell工具的流量特征分析

又来跟师傅们分享小技巧了&#xff0c;这次简单介绍一下三种常见的webshell流量分析&#xff0c;希望能对参加HW蓝队的师傅们有所帮助。 什么是webshell webshell就是以asp、php、jsp或者cgi等网页文件形式存在的一种代码执行环境&#xff0c;主要用于网站管理、服务器管理、…