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

【Python基础】迭代器

文章目录

    • @[toc]
      • 什么是迭代
      • 可迭代对象
        • 判断数据类型是否是可迭代类型
      • 迭代器
        • 对可迭代对象进行迭代的本质
        • 获取可迭代对象的迭代器
        • 通过迭代器获取数据
        • `StopIteration`异常
      • 自定义迭代器
        • `__iter__()`方法
        • `__next__()`方法
        • 判断数据类型是否是可迭代类型
        • 自定义迭代器案例
          • 分离模式
          • 整合模式
        • `for`循环的本质
      • 接收可迭代对象的方式
        • 示例

什么是迭代

  • 迭代是访问序列类型元素的一种方式
nums = [1, 2, 3, 4, 5, 6]for num in nums:print(num)
1
2
3
4
5
6
  • 可以使用for循环对stringlisttupledictset等数据类型进行遍历,从中依次获取元素,这个过程称为迭代

可迭代对象

  • 是否所有的数据类型都可以通过for循环进行迭代呢?
tel = 10086for item in tel:print(item)
Traceback (most recent call last):File "C:/Users/FOLLOW_MY_HEART/Desktop/Python基础/【Python基础】迭代器/test.py", line 3, in <module>for item in tel:
TypeError: 'int' object is not iterable
  • 通过运行发现TypeError异常,显示int类型不是iterable类型,即可迭代类型
判断数据类型是否是可迭代类型
from collections.abc import Iterable# 判断 string 类型是否是可迭代类型
print(isinstance('abcdef', Iterable))
# 判断 list 类型是否是可迭代类型
print(isinstance([], Iterable))
# 判断 tuple 类型是否是可迭代类型
print(isinstance((0, 0), Iterable))
# 判断 dict 类型是否是可迭代类型
print(isinstance({'key': 'value'}, Iterable))
# 判断 set 类型是否是可迭代类型
print(isinstance({}, Iterable))# 判断 int 类型是否是可迭代类型
print(isinstance(0, Iterable))
# 判断 float 类型是否是可迭代类型
print(isinstance(3.14, Iterable))
True
True
True
True
True
False
False
  • 可以看到stringlisttupledictset数据类型是Iterable类的实例,是可迭代类型
  • intfloat数据类型不是Iterable类的实例,不是可迭代类型

迭代器

  • 迭代器是一个记录遍历位置的对象
  • 迭代器对象从第一个元素开始访问,直至对所有的元素进行了访问
  • 迭代器只能前进,不能后退
对可迭代对象进行迭代的本质
  • 在对可迭代对象进行迭代的过程中,每迭代一步都会返回对象的下一个元素数据,一直向后读取元素数据,直至迭代了所有的元素

  • 在这个过程中应该存在记录当前遍历位置的对象,以便每一步迭代都能返回下一条数据,这个对象就是迭代器

  • 可迭代对象的本质就是提供了进行数据迭代的迭代器对象的对象类型

  • listtuple等都是可迭代对象,可以通过iter()函数获取这些可迭代对象提供的迭代器,然后可以通过对迭代器使用next()函数来获取下一条数据

获取可迭代对象的迭代器
  • 通过iter()函数获取可迭代对象的迭代器
from collections.abc import Iteratornums = [1, 2, 3, 4, 5, 6]nums_iter = iter(nums)  # 获取 list 对象的迭代器print(type(nums_iter))print(isinstance(nums, Iterator))
print(isinstance(nums_iter, Iterator))
<class 'list_iterator'>
False
True
通过迭代器获取数据
  • 通过对迭代器使用next()函数来获取下一条数据
nums = [1, 2, 3]nums_iter = iter(nums)  # 获取 list 对象的迭代器num1 = next(nums_iter)
print(num1)num2 = next(nums_iter)
print(num2)num3 = next(nums_iter)
print(num3)
1
2
3
StopIteration异常
  • 如果将上面的代码多调用一次next()会发生什么?
nums = [1, 2, 3]nums_iter = iter(nums)  # 获取 list 对象的迭代器num1 = next(nums_iter)
print(num1)num2 = next(nums_iter)
print(num2)num3 = next(nums_iter)
print(num3)num4 = next(nums_iter)  # 这里会产生异常
print(num4)
1
2
3
Traceback (most recent call last):File "C:/Users/FOLLOW_MY_HEART/Desktop/Python基础/【Python基础】迭代器/test.py", line 14, in <module>num4 = next(nums_iter)
StopIteration
  • 可以看到第 14 14 14行代码处产生了异常
  • 因为列表nums中只有 3 3 3个元素,调用 4 4 4next()显然无法获取到第 4 4 4个元素
  • 所以StopIteration异常其实是一种告知迭代结束的标志而已
  • 添加异常处理即可解决问题
nums = [1, 2, 3]nums_iter = iter(nums)  # 获取 list 对象的迭代器num1 = next(nums_iter)
print(num1)num2 = next(nums_iter)
print(num2)num3 = next(nums_iter)
print(num3)try:num4 = next(nums_iter)print(num4)
except StopIteration as e:print('迭代结束')
1
2
3
迭代结束

自定义迭代器

  • 上面提到的iter()方法必须是对可迭代对象才能提取到迭代器对象,但是怎样保证自定义对象是可迭代对象呢?
__iter__()方法
  • __iter__()方法
from collections.abc import Iterableclass MyList:def __init__(self):self.my_list = list()def add(self, item):self.my_list.append(item)mylist = MyList()print(isinstance(mylist, Iterable))
False
  • __iter__()方法
from collections.abc import Iterableclass MyList:def __init__(self):self.my_list = list()def add(self, item):self.my_list.append(item)def __iter__(self):passmylist = MyList()print(isinstance(mylist, Iterable))
True
  • 可以看出,只要一个类定义了__iter__()方法,那么这个类的实例就是可迭代对象
  • 实际上,当调用iter()方法获取一个可迭代对象的迭代器时,会自动触发这个对象的__iter__()方法,返回这个对象的迭代器
__next__()方法
  • 通过对迭代器使用next()函数能够获取下一条数据,实际上会自动触发这个对象的__next__()方法
  • 所以想要构造一个迭代器,就要实现__next__()方法
  • Python要求迭代器本身也是可迭代的,所以还要为迭代器类实现__iter__()方法,而__iter__()方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器类的__iter__()方法返回自身即可
  • 一个实现了__iter__()方法和__next__()方法的对象就是迭代器
判断数据类型是否是可迭代类型
  • 使用isinstance()判断一个对象是否是Iterator对象
from collections.abc import Iterable, Iteratornums = [1, 2, 3]print(isinstance(nums, Iterable))
print(isinstance(nums, Iterator))nums_iter = iter(nums)  # 获取 list 对象的迭代器print(isinstance(nums_iter, Iterable))
print(isinstance(nums_iter, Iterator))
True
False
True
True
自定义迭代器案例
分离模式
class MyList:def __init__(self):self.items = list()self.current = 0  # 记录当前迭代位置def add(self, value):self.items.append(value)def __iter__(self):return MyIterator(self)  # 返回一个迭代器对象class MyIterator:def __init__(self, my_list_obj):self.my_list_obj = my_list_objdef __iter__(self):return selfdef __next__(self):if self.my_list_obj.current < len(self.my_list_obj.items):item = self.my_list_obj.items[self.my_list_obj.current]self.my_list_obj.current += 1  # 当前迭代位置加 1return itemelse:raise StopIteration  # 手动抛出异常if __name__ == '__main__':my_list = MyList()my_list.add(1)my_list.add(2)my_list.add(3)iter_obj = iter(my_list)print(next(iter_obj))  # 打印 1# 打印 2、3, 思考一下为什么 for 循环从 2 开始打印for item in my_list:print(item)
1
2
3
整合模式
class MyList:def __init__(self):self.items = list()self.current = 0  # 记录当前迭代位置def add(self, value):self.items.append(value)def __iter__(self):return self  # 返回一个迭代器对象def __next__(self):if self.current < len(self.items):item = self.items[self.current]self.current += 1  # 当前迭代位置加 1return itemelse:raise StopIteration  # 手动抛出异常if __name__ == '__main__':my_list = MyList()my_list.add(1)my_list.add(2)my_list.add(3)iter_obj = iter(my_list)print(next(iter_obj))  # 打印 1# 打印 2、3, 思考一下为什么 for 循环从 2 开始打印for item in my_list:print(item)
for循环的本质
nums = [1, 2, 3, 4, 5, 6]nums_iter = iter(nums)
while True:try:print(next(nums_iter))except StopIteration:break
1
2
3
4
5
6
  • 在对可迭代对象进行迭代时,for循环先调用iter()方法,会自动触发这个对象的__iter__()方法,返回这个对象的迭代器
  • 然后,对获取到的迭代器不断调用next()方法,会自动触发这个对象的__next__()方法,返回下一条数据
  • 最后,通过处理StopIteration异常来结束循环

接收可迭代对象的方式

  • 并不是只有for循环能够接收可迭代对象
  • list()tuple()等也能接收可迭代对象
示例
class MyList:def __init__(self):self.items = list()self.current = 0  # 记录当前迭代位置def add(self, value):self.items.append(value)def __iter__(self):return self  # 返回一个迭代器对象def __next__(self):if self.current < len(self.items):item = self.items[self.current]self.current += 1  # 当前迭代位置加 1return itemelse:raise StopIteration  # 手动抛出异常if __name__ == '__main__':my_list = MyList()my_list.add(1)my_list.add(2)my_list.add(3)iter_obj = iter(my_list)print(list(iter_obj))
[1, 2, 3]
  • 对迭代器iter_obj调用list(),返回了包含迭代出的所有数据的列表

相关文章:

【Python基础】迭代器

文章目录 [toc]什么是迭代可迭代对象判断数据类型是否是可迭代类型 迭代器对可迭代对象进行迭代的本质获取可迭代对象的迭代器通过迭代器获取数据StopIteration异常 自定义迭代器__iter__()方法__next__()方法判断数据类型是否是可迭代类型自定义迭代器案例分离模式整合模式 fo…...

QVTK 可视化

#ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>#include <vtkNew.h> // 智能指针 #include <QVTKOpenGLNativeWidget.h> #include <vtkCylinderSource.h> // 圆柱#include <vtkPolyDataMapper.h&g…...

【初阶C++】入门(超详解)

C入门 前言1. C关键字(C98)2. 命名空间2.1 命名空间定义2.2 命名空间使用2.3嵌套命名空间 3. C输入&输出4. 缺省参数4.1 缺省参数概念4.2 缺省参数分类 5. 函数重载5.1 函数重载概念5.2 C支持函数重载的原理--名字修饰(name Mangling) 6. 引用6.1 引用概念6.2 引用特性6.3 …...

Java正则表达式的使用

标题&#xff1a;Java正则表达式的使用 介绍&#xff1a; 正则表达式是一种强大的文本匹配模式和搜索工具。在Java中&#xff0c;通过使用正则表达式&#xff0c;我们可以快速有效地进行字符串的匹配、查找和替换。本文将介绍Java正则表达式的基本使用方法&#xff0c;并提供相…...

Collecting Application Engine Performance Data 收集应用程序引擎性能数据

You can collect performance data of any specific SQL action of an Application Engine program to address any performance issue. 您可以收集应用程序引擎程序的任何特定SQL操作的性能数据&#xff0c;以解决任何性能问题。 You can collect performance data of the S…...

C Primer Plus阅读--章节16

C Primer Plus阅读–章节16 翻译程序的第一步 预处理之前&#xff0c;编译器必须对该程序进行一些翻译处理。 首先&#xff0c;编译器将源代码中出现的字符映射到源字符集。第二&#xff0c;编译器定位每个反斜杠后面跟着换行符的实力&#xff0c;并删除他们。物理行的合并。…...

直接插入排序与希尔排序

目录 前言 插入排序 直接插入排序 时空复杂度 直接插入排序的特性 希尔排序&#xff08;缩小增量排序&#xff09; 预排序 顺序排序 多组并排 小总结 直接插入排序 时空复杂度 希尔排序的特性 前言 字可能有点多&#xff0c;但是真的理解起来真的没那么难&#…...

敏捷:应对软件定义汽车时代的开发模式变革

随着软件定义汽车典型应用场景的落地&#xff0c;汽车从交通工具转向智能移动终端的趋势愈发明显。几十年前&#xff0c;一台好车的定义主要取决于高性能的底盘操稳与动力系统&#xff1b;几年前&#xff0c;一台好车的定义主要取决于智能化系统与智能交互能否满足终端用户的用…...

做题笔记:SQL Sever 方式做牛客SQL的题目--查询每天刷题通过数最多的前二名用户

----查询每天刷题通过数最多的前二名用户id和刷题数 现有牛客刷题表questions_pass_record&#xff0c;请查询每天刷题通过数最多的前二名用户id和刷题数&#xff0c;输出按照日期升序排序&#xff0c;查询返回结果名称和顺序为&#xff1a; date|user_id|pass_count 表单创建…...

Vue3 用 Proxy API 替代 defineProperty API 的那些事

一、Object.defineProperty 定义&#xff1a;Object.defineProperty() 方法会直接在一个对象上定义一个新属性&#xff0c;或者修改一个对象的现有属性&#xff0c;并返回此对象 1.1 为什么能实现响应式 通过defineProperty 两个属性&#xff0c;get及set get 属性的 gett…...

成都工业学院Web技术基础(WEB)实验五:CSS3动画制作

写在前面 1、基于2022级计算机大类实验指导书 2、代码仅提供参考&#xff0c;前端变化比较大&#xff0c;按照要求&#xff0c;只能做到像&#xff0c;不能做到一模一样 3、图片和文字仅为示例&#xff0c;需要自行替换 4、如果代码不满足你的要求&#xff0c;请寻求其他的…...

【Docker】学习笔记(三)三剑客之 docker-compose文件书写项目多服务容器运行

简介 引言&#xff08;需求&#xff09; 为了完成一个完整项目势必用到N多个容器配合完成项目中的业务开发&#xff0c;一旦引入N多个容器&#xff0c;N个容器之间就会形成某种依赖&#xff0c;也就意味着某个容器的运行需要其他容器优先启动之后才能正常运行&#xff1b; 容…...

node.js基础

node.js基础 &#x1f353;什么是node.js&#x1f353;node.js模块&#x1f352;&#x1f352; 内置模块&#x1f345;&#x1f345;&#x1f345;fs模块&#x1f345;&#x1f345;&#x1f345;path模块&#x1f345;&#x1f345;&#x1f345;http模块 &#x1f352;&#…...

fastapi实现websocket在线聊天

最近要实现一个在线聊天功能&#xff0c;基于fastapi的websocket实现了这个功能。下面介绍一下遇到的技术问题 1.问题难点 在线上环境部署时&#xff0c;一般是多进程的方式进行部署启动fastapi服务&#xff0c;而每个启动的进程都有自己的独立存储空间。导致存储的连接对象分…...

LLM推理部署(六):TogetherAI推出世界上LLM最快推理引擎,性能超过vLLM和TGI三倍

LLM能有多快&#xff1f;答案在于LLM推理的最新突破。 TogetherAI声称&#xff0c;他们在CUDA上构建了世界上最快的LLM推理引擎&#xff0c;该引擎运行在NVIDIA Tensor Core GPU上。Together推理引擎可以支持100多个开源大模型&#xff0c;比如Llama-2&#xff0c;并在Llama-2–…...

Unity | 渡鸦避难所-2 | 搭建场景并添加碰撞器

1 规范项目结构 上期中在导入一系列的商店资源包后&#xff0c;Assets 目录已经变的混乱不堪 开发过程中&#xff0c;随着资源不断更新&#xff0c;遵循一定的项目结构和设计规范是非常必要的。这可以增加项目的可读性、维护性、扩展性以及提高团队协作效率 这里先做下简单的…...

展望2024年供应链安全

2023年是开展供应链安全&#xff0c;尤其是开源治理如火如荼的一年&#xff0c;开源治理是供应链安全最重要的一个方面&#xff0c;所以我们从开源治理谈起。我们先回顾一下2023的开源治理情况。我们从信通院《2023年中国企业开源治理全景观察》发布的信息。信通院调研了来自七…...

React 列表页实现

一、介绍 列表页是常用的功能&#xff0c;从后端获取列表数据&#xff0c;刷新到页面上。开发列表页需要考虑以下技术要点:1.如何翻页&#xff1b;2.如何进行内容搜索&#xff1b;3.何时进行页面刷新。 二、使用教程 1.user-service 根据用户id获取用户列表&#xff0c;返回…...

【程序人生】还记得当初自己为什么选择计算机?

✏️ 初识计算机&#xff1a; 还记得人生中第一次接触计算机编程是在高中&#xff0c;第一门编程语言是Python&#xff08;很可惜由于条件限制的原因&#xff0c;当时没能坚持学下去......现在想来有点后悔&#xff0c;没能坚持&#xff0c;唉......&#xff09;。但是&#xf…...

9-tornado-Template优化方法、个人信息案例、tornado中ORM的使用(peewee的使用、peewee_async)、WTForms的使用

在很多情况下&#xff0c;前端模板中在很多页面有都重复的内容可以使用&#xff0c;比如页头、页尾、甚至中间的内容都有可能重复。这时&#xff0c;为了提高开发效率&#xff0c;我们就可以考虑在共同的部分提取出来&#xff0c; 主要方法有如下&#xff1a; 1. 模板继承 2. U…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...

Spring是如何解决Bean的循环依赖:三级缓存机制

1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间‌互相持有对方引用‌,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...

GraphQL 实战篇:Apollo Client 配置与缓存

GraphQL 实战篇&#xff1a;Apollo Client 配置与缓存 上一篇&#xff1a;GraphQL 入门篇&#xff1a;基础查询语法 依旧和上一篇的笔记一样&#xff0c;主实操&#xff0c;没啥过多的细节讲解&#xff0c;代码具体在&#xff1a; https://github.com/GoldenaArcher/graphql…...