一文读懂Python生成器和迭代器

在python中,我们经常会遇到需要对一系列的元素进行遍历或处理的情况,例如对列表中的每个元素进行求和或排序,或者对文件中的每一行进行读取或写入。为了实现这样的功能,我们通常会使用for循环或while循环来逐个获取元素,并进行相应的操作。例如:

对列表中的每个元素进行求和

lst = [1, 2, 3, 4, 5]
sum = 0
for x in lst:sum += x
print(sum) # 输出15

对文件中的每一行进行读取

f = open("test.txt", "r")
for line in f:print(line) # 输出文件内容
f.close()

在这些例子中,我们使用了一个非常重要且常见的概念:可迭代对象(iterable)。可迭代对象是指可以被for循环或其他迭代工具所遍历或处理的对象,它包含了一系列的元素,并且提供了一种方法来访问这些元素。在python中,很多内置的数据结构都是可迭代对象,如列表、元组、字典、集合、字符串等。我们也可以自定义类来实现可迭代对象,只要实现了__iter__()方法或者__getitem__()方法。

那么,当我们对一个可迭代对象进行迭代时,究竟发生了什么呢?实际上,当我们使用for循环或其他迭代工具对一个可迭代对象进行迭代时,python会自动调用该对象的__iter__()方法,该方法会返回一个迭代器(iterator)。迭代器是一个特殊的对象,它实现了__next__()方法,并且可以记住当前的迭代位置。每次调用迭代器的__next__()方法,它会返回可迭代对象中的下一个元素,直到没有更多的元素时,抛出一个StopIteration异常。例如:

创建一个可迭代对象

lst = [1, 2, 3, 4, 5]

调用可迭代对象的__iter__()方法,返回一个迭代器

it = iter(lst)

调用迭代器的__next__()方法,返回可迭代对象中的下一个元素

print(next(it)) # 输出1
print(next(it)) # 输出2
print(next(it)) # 输出3
print(next(it)) # 输出4
print(next(it)) # 输出5
print(next(it)) # 抛出StopIteration异常

从上面的代码可以看出,迭代器是一个非常有用的工具,它可以让我们方便地访问可迭代对象中的元素,而不需要知道可迭代对象的内部结构或实现细节。我们也可以自定义类来实现迭代器,只要实现了__iter__()方法和__next__()方法。例如:

定义一个斐波那契数列类,实现了可迭代对象和迭代器的接口

class Fibonacci:def __init__(self, n):self.n = n # 斐波那契数列的长度self.a = 0 # 第一个数self.b = 1 # 第二个数self.i = 0 # 当前的索引def __iter__(self):return self # 返回自身作为迭代器def __next__(self):if self.i < self.n: # 如果还有下一个元素x = self.a # 记录当前的数self.a, self.b = self.b, self.a + self.b # 更新下一个数和下下一个数self.i += 1 # 更新当前的索引return x # 返回当前的数else: # 如果没有下一个元素raise StopIteration # 抛出StopIteration异常

创建一个斐波那契数列对象,长度为10

fib = Fibonacci(10)

对斐波那契数列对象进行迭代,打印每个元素

for x in fib:print(x) # 输出0, 1, 1, 2, 3, 5, 8, 13, 21, 34

从上面的代码可以看出,我们可以通过自定义类来实现任意复杂的迭代逻辑,只要遵循了可迭代对象和迭代器的接口。但是,这样做也有一些缺点,如:

我们需要编写很多样板代码,如__iter__()方法和__next__()方法。
我们需要手动维护当前的迭代状态,如索引、变量等。
我们需要手动处理迭代结束的情况,如抛出异常等。
为了解决这些问题,python提供了一种更简洁而强大的工具:生成器(generator)。生成器是一种特殊的函数,它使用了yield关键字来返回一个值,并且暂停执行。当再次调用生成器时,它会从上次暂停的地方继续执行,直到遇到下一个yield关键字或者函数结束。生成器本质上也是一种迭代器,它可以被for循环或其他迭代工具所遍历或处理。使用生成器,我们可以用更简单而优雅的方式来实现复杂的迭代逻辑,而不需要编写很多样板代码或维护很多状态。例如:

定义一个斐波那契数列生成器函数,使用yield关键字返回每个数

def fibonacci(n):a = 0 #

接下来,我们将看看如何使用生成器函数,以及它们的优势和局限性。

要使用生成器函数,我们只需要像调用普通函数一样,传入相应的参数,并赋值给一个变量。这个变量就是一个生成器对象,它实现了迭代器的接口,可以被for循环或其他迭代工具所遍历或处理。例如:

# 创建一个斐波那契数列生成器对象,长度为10
fib = fibonacci(10)# 对斐波那契数列生成器对象进行迭代,打印每个元素
for x in fib:print(x) # 输出0, 1, 1, 2, 3, 5, 8, 13, 21, 34

从上面的代码可以看出,使用生成器函数非常简单而方便,我们不需要编写很多样板代码或维护很多状态。生成器函数还有以下的优势:

生成器函数是惰性的,它只在需要时才计算下一个元素,而不是一次性生成所有的元素。这样可以节省内存空间和计算时间,特别是对于大规模或无限的数据集。
生成器函数是可组合的,我们可以将多个生成器函数连接起来,形成一个复杂的数据流。例如,我们可以使用itertools库中提供的各种生成器函数来实现各种排列、组合、过滤、映射等操作。
生成器函数是可重用的,我们可以多次调用同一个生成器函数,并得到相同的结果。例如,我们可以将同一个生成器对象传递给不同的函数或类,并进行不同的处理。
当然,生成器函数也有一些局限性,如:

生成器函数是单向的,我们只能从前往后获取元素,而不能从后往前或者跳跃获取元素。如果我们想要随机访问元素,我们需要将生成器对象转换成列表或其他数据结构。
生成器函数是一次性的,我们只能遍历一次元素,而不能重复遍历元素。如果我们想要多次遍历元素,我们需要重新创建生成器对象或者使用itertools.tee()函数来复制生成器对象。
生成器函数是不可预知的,我们无法提前知道元素的个数或者类型。如果我们想要获取这些信息,我们需要遍历所有的元素或者使用其他方法来估计。
这样,我们就介绍了什么是迭代器和生成器,它们有什么区别和联系。在下一个主题中,我们将介绍如何使用内置的迭代器和生成器函数,如range、enumerate、zip、map、filter等。请继续关注我的教程!

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

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

相关文章

森海塞尔为 CUPRA 首款纯电轿跑 SUV – CUPRA Tavascan 注入音频魅力

森海塞尔为 CUPRA 首款纯电轿跑 SUV – CUPRA Tavascan 注入音频魅力 音频专家森海塞尔携手富有挑战精神的 CUPRA&#xff0c;雕琢时代新贵车型&#xff0c;打造畅快尽兴的驾驶体验 全球知名音频专家森海塞尔与以颠覆传统、充满激情、不甘现状而闻名的汽车品牌 CUPRA 展开合作…

掌握Python的X篇_28_python包管理工具pip命令

本篇将会介绍在实际使用python中最能节省效率的内容&#xff0c;利用第三方库拿来就用。 文章目录 1. pip命令是什么2. pip相关操作2.1 list2.2 install2.3 uninstall2.4 导出和导入2.4.1 freeze命令2.4.2 “-r” 3. 国内镜像4. Python Packges Index网站 1. pip命令是什么 p…

SpringBoot复习:(33)WebMvcAutoconfiguration内部静态类WebMvcAutoConfigurationAdapter

WebMvcAutoconfiguration内部静态类WebMvcAutoConfigurationAdapter实现了WebMvcConfigurer接口&#xff0c;重写了一些方法&#xff0c;也就是默认对Spring Mvc进行了一些配置: 该静态类上有个**Import**注解&#xff1a; Import(EnableWebMvcConfiguration.class) 它的父类…

【uniapp】滚动相关

1、滚动到一定区域&#xff0c;顶部内容置换并置顶 功能&#xff1a; 当我向下滚动时&#xff0c;当关注那一行快到顶部的时候&#xff0c;把左侧区域的内容切换成右侧区域的内容&#xff0c;并置顶 原先我使用v-if来显示隐藏&#xff0c;发现会出现闪屏的现象&#xff0c;后来…

选读SQL经典实例笔记23_读后总结与感想兼导读

1. 基本信息 SQL经典实例 SQL Cookbook [美]安东尼莫利纳罗&#xff08;Anthony Molinaro&#xff09; / 人民邮电出版社 / 2018-07 / 其他 人民邮电出版社,2018年7月出版第1版&#xff0c;2021年12月出版第2版 1.1. 读薄率 1版书籍总字数827千字&#xff0c;笔记总字数30…

c++QT文件操作

1 介绍 QT的文件操作来源于其抽象基类QIODevice&#xff0c;中用于处理输入输出设备。提供了统一的接口来处理不同类型的数据源&#xff0c;如文件、套接字、缓冲区等。QIODevice 主要用于读取和写入数据&#xff0c;无论数据来自何种源头&#xff0c;都可以通过 QIODevice 统一…

【资料分享】全志科技T507-H开发板规格书

1 评估板简介 创龙科技TLT507-EVM是一款基于全志科技T507-H处理器设计的4核ARM Cortex-A53国产工业评估板,主频高达1.416GHz,由核心板和评估底板组成。核心板CPU、ROM、RAM、电源、晶振等所有器件均采用国产工业级方案,国产化率100%。同时,评估底板大部分元器件亦采用国产…

HarmonyOS SDK开放能力,服务鸿蒙生态建设,打造优质应用体验

华为开发者大会2023&#xff08;HDC.Together&#xff09;于8月4日至6日在东莞松山湖举行&#xff0c;在HarmonyOS端云开放能力技术分论坛上&#xff0c;华为为广大开发者们介绍了HarmonyOS SDK开放能力在基础开发架构、功能特性等方面的变化之处&#xff0c;通过将常见的通用能…

日常BUG——Java使用Bigdecimal类型报错

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;日常BUG、BUG、问题分析☀️每日 一言 &#xff1a;存在错误说明你在进步&#xff01; 一、问题描述 直接上代码&#xff1a; Test public void test22() throws ParseException {System.out.p…

【webpack】自定义loader

&#x1f4dd;个人主页&#xff1a;爱吃炫迈 &#x1f48c;系列专栏&#xff1a;前端工程化 &#x1f9d1;‍&#x1f4bb;座右铭&#xff1a;道阻且长&#xff0c;行则将至&#x1f497; 文章目录 loaderloader引入方式loader传入/接收参数传入参数接收参数 loader返回值retur…

竞赛项目 深度学习疲劳驾驶检测 opencv python

文章目录 0 前言1 课题背景2 实现目标3 当前市面上疲劳驾驶检测的方法4 相关数据集5 基于头部姿态的驾驶疲劳检测5.1 如何确定疲劳状态5.2 算法步骤5.3 打瞌睡判断 6 基于CNN与SVM的疲劳检测方法6.1 网络结构6.2 疲劳图像分类训练6.3 训练结果 7 最后 0 前言 &#x1f525; 优…

SpringBoot在线失物招领系统

一个基于SpringBootSemanticUI的pc Web在线失物招领系统 http://localhost:8080/swzl/index 主页 http://localhost:8080/swzl/login 登录页 用户表user admin字段为true是管理员 false用户 springboot2.3 springmvc mybatis html ajax idea 或eclipse maven mys…

linux 下安装部署flask项目

FlaskDemo 命名为test.py # codingutf-8 from flask import Flaskapp Flask(__name__)app.route("/") def index():return "test"if __name__ __main__:app.debug True# 这里host一定要写0.0.0.0 写127.0.0.1的无法访问 ——_——app.run(host"0.…

C++11语法笔记

文章目录 一.类中新增的默认成员函数:移动赋值和移动构造二.lambda表达式三.包装器bind函数 一.类中新增的默认成员函数:移动赋值和移动构造 二.lambda表达式 三.包装器 bind函数

背上大大书包准备run之JS篇(含Es6)

word天&#xff0c;整理都半天&#xff0c;这么多&#xff0c;不得背死我。。。 js数据类型&#xff1f; 原始类型&#xff08;Primitive types&#xff09;: 数字 (Number)&#xff1a;例如&#xff1a;42, 3.14. 字符串 (String)&#xff1a;例如&#xff1a;"Hello…

使用 PyTorch 逐步检测单个对象

一、说明 在对象检测任务中&#xff0c;我们希望找到图像中对象的位置。我们可以搜索一种类型的对象&#xff08;单对象检测&#xff0c;如本教程所示&#xff09;或多个对象&#xff08;多对象检测&#xff09;。通常&#xff0c;我们使用边界框定义对象的位置。有几种方法可以…

【Fegin技术专题】「原生态」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(上)

前提介绍 Feign是SpringCloud中服务消费端的调用框架&#xff0c;通常与ribbon&#xff0c;hystrix等组合使用。由于遗留原因&#xff0c;某些项目中&#xff0c;整个系统并不是SpringCloud项目&#xff0c;甚至不是Spring项目&#xff0c;而使用者关注的重点仅仅是简化http调…

《golang设计模式》第二部分·结构型模式-01-适配器模式(Adapter)

文章目录 1. 概念1.1 角色1.2 应用场景1.2 类图 2. 代码示例2.1 设计2.2 代码2.3 示例类图 1. 概念 定义一个适配器&#xff0c;帮助原本不能实现接口的类“实现”该接口 1.1 角色 目标&#xff08;Target&#xff09;&#xff1a;客户端调用的目标接口 被适配者&#xff08…

Linux tar包安装 Prometheus 和 Grafana

0. 介绍 用tar包的方式安装 Prometheus 和 Grafana Prometheus:开源的监控方案Grafana:将Prometheus的数据可视化平台 1. Prometheus 1. 下载 与 解压 官网下载: https://prometheus.io/download/#prometheus上传至机器解压命令:tar -xzf prometheus-*.tar.gz 2. 启动与暂…

phpspreadsheet excel导入导出

单个sheet页Excel2003版最大行数是65536行。Excel2007开始的版本最大行数是1048576行。Excel2003的最大列数是256列&#xff0c;2007以上版本是16384列。 xlswriter xlswriter - PHP 高性能 Excel 扩展&#xff0c;功能类似phpspreadsheet。它能够处理非常大的文件&#xff0…