迭代器和生成器的学习笔记

迭代器       

Python 迭代器是一种对象,它实现了迭代协议,包括 __iter__() 和 __next__() 方法。迭代器可以让你在数据集中逐个访问元素,而无需关心数据结构的底层实现。与列表或其他集合相比,迭代器可以节省内存,因为它们一次只生成一个元素。

迭代器的基本特点

  1. 懒加载:迭代器不会一次性将所有数据加载到内存中,而是根据需要生成元素。
  2. 状态保持:迭代器在迭代过程中会保持其状态,可以从上次停止的地方继续迭代。
  3. 可以遍历:迭代器是可遍历的,可以使用 for 循环等结构来进行遍历。

 下面的代码可以看出迭代器在节省内存方面的作用。

import sys
import random# 生成 1-100的随机数的集合,共1000个元素
numbers = [random.randint(1, 100) for _ in range(1000)]
iterator = iter(numbers)# 打印对象的内存大小
print(sys.getsizeof(numbers))   # 9016
print(sys.getsizeof(iterator))  # 48

 迭代器的经典demo:

# 创建一个简单的迭代器
class MyIterator:def __init__(self, limit):self.limit = limitself.current = 0def __iter__(self):return selfdef __next__(self):if self.current < self.limit:self.current += 1return self.currentelse:raise StopIteration# 使用迭代器
for num in MyIterator(5):print(num)

 迭代器在读取大文件的经典应用:

with open('users.csv', 'r') as file:for line in file:print(line.strip())

         逐行读取文件内容,而不需要将整个文件加载到内存中。这种方法节省了内存资源,特别是在处理非常大的文件时。

生成器

生成器是一种特殊类型的迭代器,它允许你在函数中暂停执行并在以后继续。 

使用 yield 的基本概念

  1. 生成器函数:当一个函数包含yield语句时,它不再是一个普通的函数,而是一个生成器函数。当调用这个函数时,它不会立即执行,而是返回一个生成器对象。

  2. 状态保留:每次调用生成器的__next__()方法(或者使用next()函数)时,生成器函数会从上次执行的位置继续执行,直到遇到下一个yield语句。在此时,函数的执行状态(包括局部变量)会被保留。

  3. 迭代:生成器可以被用于迭代,像普通的列表或其他可迭代对象一样。使用for循环可以逐个获取生成器产生的值。

# 定义一个生成器函数
def read_users():with open('users.csv', 'r') as file:for line in file:yield line.strip()r1 = read_users()  # 定义一个生成器对象
r2 = read_users()  # 定义另一个生成器对象
print(next(r1))
print(next(r1))
print(next(r1))
print(next(r1))
print(next(r2))
print(next(r2))
print(next(r2))
print(next(r2))

局部变量保留的demo

list1 = ['a', 'b', 'c', 'd', 'e', 'f']def iterator():i = 0for x in list1:yield do_something(i, x)i += 1def do_something(i, x):print(i, x)r1 = iterator()  # 定义一个生成器对象
r2 = iterator()  # 定义另一个生成器对象
next(r1)
next(r1)
next(r1)
next(r1)
next(r2)
next(r2)
next(r2)
next(r2)
next(r2)
运行结果:
0 a
1 b
2 c
3 d
0 a
1 b
2 c
3 d
4 e

更深入理解yield的“暂停”

函数每次遇到yield就暂停,它并不在意yield时来自于循环、迭代或者是在函数体内重复定义的,这意味着一个函数中可以有不止一个yield,并且每次运行到yield时,函数就暂停运行,并保存中间结果和变量,直到下一次next()后继续运行。

list1 = ['a', 'b', 'c', 'd', 'e', 'f']def iterator():for x in list1:yield print(x)yield print(x)yield print(x)yield print(x)r1 = iterator()  # 定义一个生成器对象
next(r1)
next(r1)
next(r1)
next(r1)
next(r1)
next(r1)# 运行结果:
# a
# a
# a
# a
# b
# b

可以将yield理解为一个中断标志

        可以将yield理解为一个中断标志,当生成器遇到 yield 语句时,它会暂停执行,并返回 yield 后面跟随的值或者函数。如果yield后面没有跟随内容,那么它就仅仅是一次暂停标志而已。

list1 = ['a', 'b', 'c', 'd', 'e', 'f']def iterator():i = 0for x in list1:print('loop', i)yieldi += 1print(x)r1 = iterator()  # 定义一个生成器对象
next(r1)
next(r1)
next(r1)
# 执行结果:
# loop 0
# a
# loop 1
# b
# loop 2

 yield的灵活运用

既然函数每次遇到yield就暂停,它并不在意yield时来自于循环、迭代或者是在函数体内重复定义的,而且可以将yield理解为一个中断标志,那么我们也就可以生成一个不循环的函数,通过yield达到步进执行的效果。

list1 = ['a', 'b', 'c', 'd', 'e', 'f']def iterator():i = 0print('breakpoint', i)yieldi += 1print('breakpoint', i)yieldi += 1print('breakpoint', i)yieldi += 1print('breakpoint', i)yieldi += 1print('breakpoint', i)r1 = iterator()  # 定义一个生成器对象
next(r1)
next(r1)
next(r1)
# 执行结果:
# breakpoint 0
# breakpoint 1
# breakpoint 2

注意可暂停和可迭代次数

要保证调用的次数不要大于可迭代次数或者可暂停次数,否则就会报错。

def iterator():i = 0print('breakpoint', i)i += 1yieldprint('breakpoint', i)i += 1yieldr1 = iterator()  # 定义一个生成器对象
next(r1)
next(r1)
next(r1)

上面的例子,定义了两个yield,但是next()调用了三次,所以出错。 

list1 = [1, 2, 3]def iterator():for i in list1:  # 遍历列表yield print(i)r1 = iterator()  # 定义一个生成器对象
next(r1)
next(r1)
next(r1)
next(r1)

这个,由于调用次数大于了列表的元素数量,也会出错。

采取措施,避免程序崩溃

1、使用try

def iterator():i = 0print('breakpoint', i)i += 1yieldprint('breakpoint', i)i += 1yieldr1 = iterator()  # 定义一个生成器对象def next_do():try:next(r1)except StopIteration:print("No more items to yield")next_do()
next_do()
next_do()
next_do()
list1 = [1, 2, 3]def iterator():for i in list1:  # 遍历列表yield print(i)r1 = iterator()  # 定义一个生成器对象def next_do():try:next(r1)except StopIteration:print("No more items to yield")next_do()
next_do()
next_do()
next_do()
next_do()# 运行结果:
# 1
# 2
# 3
# No more items to yield
# No more items to yield

2、指定next()的默认返回值参数,如果指定了该参数,并且迭代器没有更多的值可返回,则返回该参数的值,而不是引发 StopIteration 异常。

def iterator():i = 0print('breakpoint', i)i += 1yieldprint('breakpoint', i)i += 1yielddef next_do():if next(r1, 'END'):print('No more items to yield')r1 = iterator()  # 定义一个生成器对象next_do()
next_do()
next_do()
next_do()
next_do()# 运行结果:
# breakpoint 0
# breakpoint 1
# No more items to yield
# No more items to yield
# No more items to yield

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

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

相关文章

胤娲科技:谷歌DeepMind祭出蛋白质设计新AI——癌症治疗迎来曙光

在科技的浩瀚星空中&#xff0c;DeepMind的“阿尔法”家族总是能带来令人瞩目的璀璨光芒。这一次&#xff0c;它们再次以惊人的姿态&#xff0c; 将AI的触角深入到了生命的微观世界——蛋白质设计领域&#xff0c;为我们描绘了一幅未来医疗的宏伟蓝图。 想象一下&#xff0c;一…

Scrapy爬虫实战——某瓣250

# 按照我个人的习惯&#xff0c;在一些需要较多的包作为基础支撑的项目里&#xff0c;习惯使用虚拟环境&#xff0c;因为这样能极大程度的减少出现依赖冲突的问题。依赖冲突就比如A、B、C三个库&#xff0c;A和B同时依赖于C&#xff0c;但是A需要的C库版本大于N&#xff0c;而B…

VUE3配置路由(超级详细)

第一步创建vue3的项目

多版本node管理工具nvm

什么是nvm&#xff1f; 在项目开发过程中&#xff0c;使用到vue框架技术&#xff0c;需要安装node下载项目依赖&#xff0c;但经常会遇到node版本不匹配而导致无法正常下载&#xff0c;重新安装node却又很麻烦。为解决以上问题&#xff0c;nvm&#xff1a;一款node的版本管理工…

微服务-- Sentinel的使用

目录 Sentinel&#xff1a;微服务的哨兵 生态系统景观 sentinel与spring cloud Hystrix 对比 Sentinel 主要分为两部分 Sentinel安装与使用 Sentinel的控制规则 流控规则 流控规则的属性说明 新增流控规则 关联流控模式 SentinelResource注解的使用 SentinelResou…

mysql-死锁

文章目录 1、概念1.1、创建表 account1.2、id 自动创建 主键索引 primary1.3、name 没有创建索引 2、产生死锁的必要条件2.1、此时 name 没有创建 索引 3、如何处理死锁3.1、方式1&#xff1a;等待&#xff0c;直到超时&#xff08;innodb_lock_wait_timeout50s&#xff09;3.2…

GRE隧道在实际部署中的优化、局限性与弊端

GRE的其他特性 上一篇光讲解配置就花了大量的篇幅&#xff0c;还一些特性没有讲解的&#xff0c;这里在来提及下。 1、动态路由协议 在上一篇中是使用的静态路由&#xff0c;那么在动态路由协议中应该怎么配置呢&#xff1f; undoip route-static 192.168.20.0 255.255.255.0 …

element-plus的菜单组件el-menu

菜单是几乎是每个管理系统的软件系统中不可或缺的&#xff0c;element-plus提供的菜单组件可以快速完成大部分的菜单的需求开发&#xff0c; 该组件内置和vue-router的集成&#xff0c;使用起来很方便。 主要组件如下 el-menu 顶级菜单组件 主要属性 mode:决定菜单的展示模式…

2024/9/20 使用QT实现扫雷游戏

有三种难度初级6x6 中级10x10 高级16x16 完成游戏 游戏失败后&#xff0c;无法再次完成游戏&#xff0c;只能重新开始一局 对Qpushbutton进行重写 mybutton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QObject> #include <QWidget> #include <QPus…

2024年8月HarmonyOS鸿蒙应用开发者高级认证全新题库

有题库在手&#xff0c;一小时轻松拿下鸿蒙高级。你们需要也可以无偿分享哦&#xff01; 项目需要为不同的设备形态(如手机 、 智能手表)提供定制化构建 。请说明如何在 DevEcostudio 中 设置不同的构建配置&#xff0c; 以生成针对不同设备的 hap 包&#xff1a; 在模块级别 b…

JavaWeb的Filter详解

过滤器Filter 什么是Filter&#xff1f; 依据字面上的中文意思为过滤器。Filter的作用 当用户的请求到达指定的URL之前&#xff0c;可以借助Filter来改变这些请求的内容&#xff1b;同样地&#xff0c;当响应结果到达客户端之前&#xff0c;可以使用Filter修改输出的内容。什么…

【数据结构入门】排序算法之三路划分与非比较排序

文章目录 前言 一、三路划分优化 1.1. 基本思想 1.2. 实现步骤 1.3. 优点 1.4 代码实现 二、非比较排序 2.1 计数排序 2.1.1基本思想 2.1.2具体步骤 2.1.3算法特性 2.1.4算法实现 2.2 基数排序 2.2.1基本思想 2.2.2具体步骤 2.2.3 基数排序的方法 2.2.4算法特…

MongoDB在Linux系统中的安装与配置指南

在这篇文章中&#xff0c;我们将介绍如何在CentOS 7服务器上安装MongoDB&#xff0c;并通过DataX将数据从MongoDB迁移到MySQL数据库。这将包括MongoDB的安装、配置、数据准备以及使用DataX进行数据迁移的详细步骤。 MongoDB简介 MongoDB是一个高性能、开源、无模式的文档型数据…

Leetcode面试经典150题-97.交错字符串

给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串 &#xff1a; s s1 s2 ... snt t1 t2 ... tm|n - m| < 1交错 是…

Springboot3 + MyBatis-Plus + MySql + Uniapp 实现商品规格选择sku(附带自设计数据库,最新保姆级教程)

Springboot3 MyBatis-Plus MySql Uniapp 实现商品规格选择sku&#xff08;附带自设计数据库&#xff0c;最新保姆级教程&#xff09; 1、效果展示2、数据库设计2.1 商品表2.2 商品价格和规格中间表2.3 商品规格表 3、后端代码3.1 model3.2 vo3.3 mapper、server、serverImp3…

使用express或koa或nginx部署history路由模式的单页面应用

使用hash模式会有#&#xff0c;影响美观&#xff0c;所以使用history模式会是个更好的选择。 前端项目打包上线部署&#xff0c;可以使用下面的方式部署history模式的项目&#xff0c;下面以 jyH5 为例 expressjs部署 express脚手架搭建的app.js中添加如下代码&#xff1a; …

CDA Level 1 业务数据分析

目录 理解业务数据分析方法、掌握业务数据分析流程、能够使用及设计创建业务指标、能够结合业务模型及业务分析方法正确理解业务问题&#xff0c;找到问题原因&#xff0c;并能够提出解决问题建议&#xff0c;这个章节的应用会考的比较多&#xff08;终于正经起来了呢&#xf…

设计模式 组合模式(Composite Pattern)

组合模式简绍 组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端可以用一致的方式处理单个对象和组合对象。这样&#xff0c;可以在不知道对象具体类型的条…

7--SpringBoot-后端开发、原理详解(面试高频提问点)

目录 SpringBoot原理 起步依赖 自动配置 配置优先级 Bean设置 获取Bean 第三方Bean SpringBoot原理 内容偏向于底层的原理分析 基于Spring框架进行项目的开发有两个不足的地方&#xff1a; 在pom.xml中依赖配置比较繁琐&#xff0c;在项目开发时&#xff0c;需要自己去找…

手写Spring

简单实现Spring基于注解配置 ComponentScan Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface ComponentScan {String value() default ""; } 相当于component-scan HspSpringConfig ComponentScan(value "spring.write.com…