Python迭代器与生成器研究记录

Python迭代器与生成器研究记录

前言

迭代器肯定是可迭代对象,但是可迭代对象不一定是迭代器,生成器一定是迭代器,但是迭代器不一定是生成器
生成器是特殊的迭代器,所以生成器一定是迭代器,迭代器一定是可迭代对象
我们平常接触最多的对象中,字符串,字典,列表,集合,元组和open打开的文件对象等都是可迭代的对象因为他们都有__iter__()方法,可以遍历
需要注意的是,我们平常接触最多的对象中,字符串,字典,列表,集合,元组等都不是迭代器因为他们都没有__next__()方法,但是open打开的文件对象却是一个迭代器对象

# obj.__next__()方法 等价于next(obj)
# obj.__iter__()方法 等价于iter(obj)test_list = [10, 20, 30, 40]
generator_obj = (i for i in test_list)
print(generator_obj) # <generator object <genexpr> at 0x0000029852C98C00>
print(generator_obj.__next__())  # 10
print(generator_obj.__iter__())  # <generator object <genexpr> at 0x0000027411078C00>
print(next(generator_obj))  # 20
print(iter(generator_obj))  # <generator object <genexpr> at 0x0000027411078C00>

可迭代对象

1.只要内部有__iter__()方法的对象就是可迭代对象如 字符串,字典,列表集合,元组,包括open打开的文件对象也都是可迭代对象
2.或者可以这样说,只要可以转换成迭代器的对象就是可迭代对象

这些都是可迭代对象

test_list = [1, 3, 4, 7]
test_list.__iter__()
test_str = "test_str"
test_str.__iter__()
test_dict = {"1":12}
test_dict.__iter__()
test_set = {"1", "4", "898"}
test_set.__iter__()
with open("file_path", "r") as file_obj:file_obj.__iter__()

可迭代对象调用__iter__()方法会返回一个迭代器,代码如下

test_list = [1, 3, 4, 7]
print(test_list.__iter__())
print(type(test_list.__iter__()))
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
# <list_iterator object at 0x000001CEB3AD5518>
# <class 'list_iterator'>

迭代器

迭代器就是有__iter__()方法和__next()__方法的对象,所以迭代器肯定是可迭代对象,但是可迭代对象不一定是迭代器
迭代器对象调用__next__()方法每次会拿到迭代器里面的一个值并返回,直到全部拿完会报错StopIteration
迭代器对象调用__iter__()方法返回的是迭代器本身(和没调用一样),可迭代但是非迭代器的对象调用__iter__()方法也是返回的是基于这个对象的迭代器

需要注意的是,我们平常接触最多的对象中,字符串,字典,列表,集合,元组等都不是迭代器因为他们都没有__next__()方法,但是open打开的文件对象却是一个迭代器对象

# 迭代器的一个特征就是有__next__()方法
test_list = [1, 3, 4, 7]
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
list_iterator_obj = test_list.__iter__()# 迭代器调用_next__()方法每次就会拿出这个迭代器里面的一个值,直到全部拿完会报错
for i in range(5):print(list_iterator_obj.__next__())# 1
# 3
# 4
# 7
# Traceback (most recent call last):
#   File "C:/Users/xxx/Desktop/python_test_dir/test_4.py", line 10, in <module>
#     print(list_iterator_obj.__next__())
# StopIteration

迭代器对象调用__iter__()方法返回的是他自己,和没调用一样

# 迭代器的特征就是有__next__()方法
test_list = [1, 3, 4, 7]
# 可迭代对象调用__iter__()方法返回的就是一个迭代器
list_iterator_obj = test_list.__iter__()# 迭代器对象调用__iter__()方法返回的是他自己,和没调用一样
list_iterator_obj2 = list_iterator_obj.__iter__()
print(list_iterator_obj2 is list_iterator_obj)      # Trueprint(list_iterator_obj.__next__())     # 1
print(list_iterator_obj.__next__())     # 3
# 注意这里会返回此迭代器对象直接理解为是 list_iterator_obj = list_iterator_obj (因为是返回自己,所以里面剩余的值状态也是一样的)
list_iterator_obj = list_iterator_obj.__iter__()
print(list_iterator_obj.__next__())     # 4
print(list_iterator_obj.__next__())     # 7

for 循环遍历的本质可以理解成
1,每次调用此对象的__iter__()方法返回这个对象的迭代器版本
2,调用第一步返回的此迭代器版本的__next__()方法拿出里面的一个值
3,循环执行第二步直到所有元素拿完for 循环捕获结束时抛出的StopIteration异常并结束

生成器

生成器可以理解为自己定义的一个迭代器,可以自定义一个生成器,生成器定义有两种方法
1.函数yield关键字返回,含有yield关键字的函数会返回一个生成器对象,对此对象调用__next__()方法会执行此函数对应的yield关键字之前的代码并且返回yield关键字字后的返回值然后截止,下次调用__next__()方法又可以在上次的基础上继续执行
2.生成器表达式(我们以为的"元组推导式"就是生成器表达式,需要注意元组因为是不可变的所以元组没有推导式,类似元组推导式的形式其实是生成器表达式)

函数yield关键字生成器

def test():print("第一次执行")yield 1print("第二次执行")yield 2print("第三次执行")yield 3print("第四次执行")yield 4print("最后一次执行")# test函数返回一个生成器对象
generator_obj = test()print(generator_obj)  # <generator object test at 0x000001B393528C00>print(generator_obj.__next__())
# 第一次执行
# 1
print(generator_obj.__next__())
# 第二次执行
# 2
print(generator_obj.__next__())
# 第三次执行
# 3
print(generator_obj.__next__())
# 第四次执行
# 4
print(generator_obj.__next__())
# 最后一次执行
# Traceback (most recent call last):
#   File "C:/Users/xxx/Desktop/python_test_dir/test_4.py", line 51, in <module>
#     print(generator_obj.__next__())
# StopIteration

生成器表达式

test_list = [10, 20, 30, 40]
generator_obj = (i for i in test_list)
print(generator_obj) # <generator object <genexpr> at 0x0000029852C98C00>
print(generator_obj.__next__())  # 10
print(generator_obj.__next__())  # 20
print(generator_obj.__next__())  # 30
print(generator_obj.__next__())  # 40

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

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

相关文章

YOLOv8分割训练及分割半自动标注

YOLOv8是基于目标检测算法YOLOv5的改进版,它在YOLOv5的基础上进行了优化和改进,加入了一些新的特性和技术,如切片注意力机制、骨干网络的选择等。 本文以yolov8-seg为基准,主要整理分割训练流程及使用v8分割模型进行半自动标注的过程。 一、v8-seg训练 1.1 环境配置 github…

【Altera】平台设计器互连会回压 AXI 接口怎么办

说明 实现 AXI 接口的所有组件都具有发行或接受能力设置。每当互连检测到管理器&#xff08;主管理器&#xff09;发出的事务多于管理器的发行容量设置时&#xff0c;互连将通过断言 AxREADY 向管理器背压。每当互连检测到从属&#xff08;从站&#xff09;接收的事务多于从属的…

实用篇 | 一文快速构建人工智能前端展示streamlit应用

----------------------- &#x1f388;API 相关直达 &#x1f388;-------------------------- &#x1f680;Gradio: 实用篇 | 关于Gradio快速构建人工智能模型实现界面&#xff0c;你想知道的都在这里-CSDN博客 &#x1f680;Streamlit :实用篇 | 一文快速构建人工智能前端展…

Activity从下往上弹出视差效果实现

其实这篇文章是转至简书上的大佬的&#xff0c;加上我自己的代码实践了下发现可行&#xff0c;于是就分享下 先看效果 介绍: 其实有很多方法都可以实现这种效果&#xff0c;popwindow&#xff0c;Dialog&#xff0c;BottomSheetDialogFragment&#xff0c;BottomSheetDialog等…

Linux 安装 Gitea.md

### 从官网下载git 和 gitea Git下载地址: https://mirrors.edge.kernel.org/pub/software/scm/git/ 下载 git-2.43.0.tar.gz: https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.43.0.tar.gz Gitea下载地址: https://dl.gitea.com/gitea/ 下载 linux-arm64 的二进…

链表OJ—相交链表

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 1、相交链表的题目&#xff1a; 方法讲解&#xff1a; 图文解析&#xff1a; 代码实现&#xff1a; 总结 前言 世上有两种耀眼的光芒&#xff0c;一种是正在升…

15.Java程序设计-基于SSM框架的微信小程序校园求职系统的设计与实现

摘要&#xff1a; 本研究旨在设计并实现一款基于SSM框架的微信小程序校园求职系统&#xff0c;以提升校园求职流程的效率和便捷性。通过整合微信小程序平台和SSM框架的优势&#xff0c;本系统涵盖了用户管理、职位发布与搜索、简历管理、消息通知等多个功能模块&#xff0c;为…

爱智EdgerOS之深入解析AI图像引擎如何实现AI视觉开发

一、前言 AI 视觉是为了让计算机利用摄像机来替代人眼对目标进行识别&#xff0c;跟踪并进一步完成一些更加复杂的图像处理。这一领域的学术研究已经存在了很长时间&#xff0c;但直到 20 世纪 70 年代后期&#xff0c;当计算机的性能提高到足以处理图片这样大规模的数据时&am…

ArkUI组件

目录 一、概述 声明式UI 应用模型 二、常用组件 1、Image&#xff1a;图片展示组件 示例 配置控制授权申请 2、Text&#xff1a;文本显示组件 示例 3、TextInput&#xff1a;文本输入组件 示例 4、Button&#xff1a;按钮组件 5、Slider&#xff1a;滑动条组件 …

Swagger PHP Thinkphp 接口文档

安装 1. 安装依赖 composer require zircote/swagger-php 2. 下载Swagger UI git clone https://github.com/swagger-api/swagger-ui.git 3. 复制下载好的Swagger UI 中的dist目录到public目录中&#xff0c;修改目录名称 cp -rf swagger-ui/dist /home/htdocs/public/ m…

vue中设置滚动条的样式

在vue项目中&#xff0c;想要设置如下图中所示滚动条的样式&#xff0c;可以采用如下方式&#xff1a; ​// 直接写在vue.app文件中 ::-webkit-scrollbar {width: 3px;height: 3px; } ::-webkit-scrollbar-thumb { //滑块部分// border-radius: 5px;background-color: #1890ff;…

【智能家居】智能家居项目

智能家居项目目录 项目目录结构 完整而典型的项目目录结构 CMake模板 CMake编译运行 README.md 项目说明文档 智能家居项目目录 【智能家居】面向对象编程OOP和设计模式(工厂模式) 【智能家居】一、工厂模式实现继电器灯控制 【智能家居】二、添加火灾检测模块&#xff08;…

4-Docker命令之docker ps

1.docker ps介绍 docker ps命令是用来列出容器的相关信息 2.docker ps用法 docker ps [参数] [rootcentos79 ~]# docker ps --helpUsage: docker ps [OPTIONS]List containersAliases:docker container ls, docker container list, docker container ps, docker psOptions…

【重点】【二叉树】199.二叉树的右视图

题目 法1:层次遍历 最佳方法&#xff0c;牢记&#xff01;&#xff01;&#xff01; class Solution {public List<Integer> rightSideView(TreeNode root) {List<Integer> res new ArrayList<>();if (root null) {return res;}Queue<TreeNode> q…

Java 克隆:复制构造函数与克隆

为了实现克隆&#xff0c;我们需要配置我们的类并遵循以下步骤&#xff1a; 在我们的类或其超类或接口中实现 Cloneable 接口。 定义一个应处理 CloneNotSupportedException&#xff08;抛出或记录&#xff09;的 clone() 方法。 并且&#xff0c;在大多数情况下&#xff0c;我…

Ubuntu上svn基本使用(gitee提交下载)

目录 环境准备 1. 获取代码到本地 直接获取 获取代码时加入用户名密码 指定版本更新 2. 提交代码 3. 展示代码列表 4. 添加代码文件(目录) 5. 删除gitee仓库中的文件 参考文档链接 环境准备 当前操作系统为Ubuntu22.04LTS gitee 创建仓库时 需要打开svn的支持 sudo…

GoLong的学习之路,进阶,微服务之使用,RPC包(包括源码分析)

今天这篇是接上上篇RPC原理之后这篇是讲如何使用go本身自带的标准库RPC。这篇篇幅会比较短。重点在于上一章对的补充。 文章目录 RPC包的概念使用RPC包服务器代码分析如何实现的&#xff1f;总结Server还提供了两个注册服务的方法 客户端代码分析如何实现的&#xff1f;如何异步…

nginx配置正向代理支持https

操作系统版本&#xff1a; Alibaba Cloud Linux 3.2104 LTS 64位 nginx版本&#xff1a; nginx-1.25.3 1. 下载软件 切换目录 cd /server wget http://nginx.org/download/nginx-1.25.3.tar.gz 1.1解压 tar -zxvf nginx-1.25.3.tar.gz 1.2切换到源码所在目录…

【探索Linux】—— 强大的命令行工具 P.21(多线程 | 线程同步 | 条件变量 | 线程安全)

阅读导航 引言一、线程同步1. 竞态条件的概念2. 线程同步的概念 二、条件变量1. 条件变量函数⭕使用前提&#xff08;1&#xff09;初始化条件变量&#xff08;2&#xff09;等待条件满足&#xff08;3&#xff09;唤醒等待pthread_cond_broadcast()pthread_cond_signal() &…