初识迭代器(Iterator)——迭代器模式——迭代加深(后续更新...)

学习网页:

Welcome to Python.orgicon-default.png?t=N7T8https://www.python.org/

迭代器(Iterator)

迭代器是一个非常有用的Python特性,它允许我们遍历一个容器(如列表、元组、字典、集合等)的元素。迭代器提供了一种方法,可以逐个访问这些元素,而不需要一次性加载所有元素到内存中。

迭代器实现了两个关键的方法:__iter__() 和 __next__()

  • __iter__() 方法返回迭代器对象本身。
  • __next__() 方法返回容器的下一个值。当容器中没有更多元素时,它将引发 StopIteration 异常。

这是一个简单的迭代器示例,该迭代器产生从0到给定数字的平方:

class Squares:  def __init__(self, max):  self.max = max  self.n = 0  def __iter__(self):  return self  def __next__(self):  if self.n < self.max:  result = self.n ** 2  self.n += 1  return result  else:  raise StopIteration  # 使用这个迭代器  
squares = Squares(5)  
print(list(squares))  # 输出: [0, 1, 4, 9, 16]


在上面的例子中,__iter__() 方法返回迭代器对象本身,而 __next__() 方法则负责生成下一个平方数。当所有的平方数都被生成后,__next__() 方法引发一个 StopIteration 异常,表示迭代已经结束。

在Python中,你可以使用 for 循环来使用迭代器。当你使用 for 循环遍历一个容器时,Python会自动为这个容器创建一个迭代器,并使用 __next__() 方法逐个访问容器的元素。当 __next__() 方法引发 StopIteration 异常时,for 循环自动停止。

总而言之,

迭代器是一个强大的工具,它使得我们能够遍历各种数据结构,如列表、元组、字典、集合等,而无需一次性将所有元素加载到内存中。通过使用迭代器,我们可以逐个访问元素,而不是一次性加载所有元素。

在Python中,迭代器实现了两个关键的方法:__iter__() 和 __next__()__iter__() 方法返回迭代器对象本身,而 __next__() 方法则负责返回容器的下一个值。当容器中没有更多元素时,__next__() 方法将引发 StopIteration 异常,表示迭代已经结束。

我们可以自定义迭代器类来满足特定的需求。例如,上面的示例展示了一个名为 Squares 的迭代器类,它生成从0到给定数字的平方。我们可以使用 for 循环来使用这个迭代器,Python会自动调用 __next__() 方法来逐个访问平方数。当所有的平方数都被访问后,__next__() 方法引发 StopIteration 异常,for 循环自动停止。

使用迭代器可以节省内存空间,因为它允许我们逐个访问元素,而不是一次性加载所有元素。此外,迭代器还提供了更灵活的遍历方式,我们可以使用 while 循环和手动调用 __next__() 方法来遍历容器。

迭代器模式

迭代器模式是一种行为型设计模式,它提供了一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

在迭代器模式中,主要有以下几个参与者:

  1. Iterator(迭代器):迭代器定义访问和遍历元素的接口。
  2. ConcreteIterator(具体迭代器):具体迭代器实现迭代器接口,对该聚合遍历时跟踪当前位置。
  3. Aggregate(聚合):聚合定义创建相应迭代器对象的接口。
  4. ConcreteAggregate(具体聚合):具体聚合实现聚合接口,定义了创建相应迭代器对象的接口。
迭代器模式的主要优点包括:
  1. 简单性:通过使用迭代器,我们可以更简单地遍历容器中的元素,而无需了解容器的内部实现。
  2. 封装性:迭代器模式将对象的内部结构和遍历的过程都封装在迭代器中了,增加了系统的稳定性和可维护性。
  3. 抽象性:通过使用迭代器,我们可以抽象地处理不同类型的容器,而无需关心具体的容器实现。

然而,迭代器模式也有一些缺点

  1. 增加了系统的复杂性:使用迭代器模式需要额外的代码来实现迭代器和聚合类,增加了系统的复杂性。
  2. 性能问题:使用迭代器模式可能会比直接使用循环语句更慢,因为需要调用额外的函数和方法。
  3. 内存开销:由于需要创建额外的迭代器和聚合对象,因此可能会增加内存开销。

总之,迭代器模式是一种非常有用的设计模式,它提供了一种简单、封装性和抽象性的方法来遍历容器中的元素。但是,在使用时需要注意其缺点和限制。

迭代器模式是一种行为型设计模式,它提供了一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示。

”举个Java栗子“

以下是一个使用迭代器模式的简单例子(Java)

假设我们有一个班级,班级中有多个学生。我们想要遍历班级中的所有学生,并打印每个学生的姓名。

首先,我们定义一个迭代器接口:

public interface StudentIterator { 
boolean hasNext(); 
String next(); 
}

然后,我们定义一个班级类,该类实现了迭代器接口:

public class Classroom implements StudentIterator { private List<String> students; private int currentIndex; public Classroom(List<String> students) { this.students = students; this.currentIndex = 0; } @Override public boolean hasNext() { return currentIndex < students.size(); } @Override public String next() { if (hasNext()) { return students.get(currentIndex++); } else { throw new NoSuchElementException("No more students in the class."); } } }
现在,我们可以使用迭代器来遍历班级中的所有学生:
List<String> students = Arrays.asList("Alice", "Bob", "Charlie"); 
Classroom classroom = new Classroom(students); 
while (classroom.hasNext()) { 
System.out.println(classroom.next()); 
}

输出结果为:

Alice
Bob
Charlie

在这个例子中,我们定义了一个班级类,该类实现了迭代器接口。在迭代器接口中,我们定义了hasNext()next()方法,用于判断是否还有下一个元素和获取下一个元素。在班级类中,我们实现了这两个方法,并使用一个列表来存储学生姓名。然后,我们使用一个while循环来遍历班级中的所有学生,并打印每个学生的姓名。

”举个Python栗子“
class TreeNode:  def __init__(self, value):  self.value = value  self.children = []  class TreeIterator:  def __init__(self, root):  self.stack = [root]  def hasNext(self):  return len(self.stack) > 0  def next(self):  node = self.stack.pop()  if node.children:  self.stack.extend(node.children[::-1])  return node.value  # 创建一棵树  
root = TreeNode(1)  
child1 = TreeNode(2)  
child2 = TreeNode(3)  
child3 = TreeNode(4)  
root.children = [child1, child2]  
child1.children = [child3]  # 创建迭代器对象  
iterator = TreeIterator(root)  # 遍历树并打印每个节点的值  
while iterator.hasNext():  print(iterator.next())

输出结果为:

1
2
4
3

在这个例子中,我们定义了一个TreeNode类来表示树的节点,每个节点有一个值和一个子节点列表。然后我们定义了一个TreeIterator类来实现迭代器模式,它使用一个栈来存储要遍历的节点。在hasNext()方法中,我们检查栈是否为空;在next()方法中,我们从栈中弹出一个节点,并将其子节点(如果有的话)加入栈中。最后,我们使用一个while循环来遍历树并打印每个节点的值。

总结

在迭代器模式中,通过使用迭代器,我们可以更简单地遍历容器中的元素,而无需了解容器的内部实现。此外,迭代器模式还增加了系统的稳定性和可维护性,因为将容器的内部结构和遍历的过程都封装在迭代器中了。

使用迭代器模式可以抽象地处理不同类型的容器,而无需关心具体的容器实现。例如,我们可以编写一个通用的程序来遍历任何支持迭代器的容器,而无需了解容器的具体实现细节。

迭代加深

迭代加深是一种优化深度优先搜索(DFS)的方法。在深度优先搜索中,如果存在一个搜索树,树的深度很大,但答案却在深度很浅的右半部分子树中,DFS会搜索很多无用的节点。

迭代加深通过以下步骤来优化DFS:

  1. 在搜索深度限制为d时,重复搜索第1~d-1层的节点。
  2. 如果在第d-1层搜索失败了,扩大一层后,到了第d层,但我们还是得从第1层开始搜索。
  3. 重复这个过程,直到找到答案。

这种方法在搜索树的规模随着层次的深入增长很快,并且我们能够确保答案在一个较浅的节点时,可以有效地减少搜索的时间和空间复杂度。

好的,以下是一个使用迭代加深优化深度优先搜索的例子

假设我们有一个二叉树,树中的每个节点都有一个值。我们的目标是找到一个节点,使得该节点的值大于其子节点的值之和。

我们可以使用深度优先搜索来找到这个节点。但是,如果我们直接进行深度优先搜索,可能会搜索很多无用的节点,因为答案可能存在于深度很浅的节点中。

使用迭代加深可以优化这个搜索过程。我们可以从根节点开始进行深度为1的搜索。如果搜索失败,我们增加搜索的深度,直到达到一个预定的最大深度。在每次增加深度时,我们都会从最浅的层开始重新搜索,以避免重复搜索已经访问过的节点。

例如,假设我们有一个如下的二叉树:(markdown)

1  
/  \  
2    3  
/  \  
4    5

我们可以使用迭代加深来找到一个节点,使得该节点的值大于其子节点的值之和。首先,我们从根节点1开始进行深度为1的搜索。如果搜索失败,我们增加搜索的深度,直到达到最大深度3。在每次增加深度时,我们都会从最浅的层开始重新搜索。

在第一次搜索时,我们选择左子节点2作为当前节点。然后,我们检查2的右子节点是否存在,如果存在,我们继续搜索右子树;如果不存在,我们回到上一层并选择3作为当前节点。重复这个过程,直到找到答案或者达到最大深度。

在上述例子中,答案是3的父节点2,因为2的值大于其子节点2和3的值之和。使用迭代加深可以有效地减少搜索的时间和空间复杂度,避免在无用的节点上浪费时间和空间。

总结

在迭代加深中,我们首先从根节点开始进行深度为1的搜索。如果搜索失败,我们增加搜索的深度,直到达到一个预定的最大深度。在每次增加深度时,我们都会从最浅的层开始重新搜索,以避免重复搜索已经访问过的节点。

这种方法的主要优点是它可以有效地减少搜索的时间和空间复杂度。在深度很大的搜索树中,如果我们直接进行深度优先搜索,可能会浪费很多时间和空间。而迭代加深通过逐步增加搜索的深度来寻找答案,可以避免在无用的节点上浪费时间和空间。

此外,迭代加深还可以与其他优化技术结合使用,如剪枝、启发式搜索等,进一步提高搜索的效率。

需要注意的是,迭代加深并不适用于所有情况。如果搜索树的大小随着深度的增加而迅速增长,或者答案可能存在于深度很大的节点中,那么直接进行深度优先搜索可能会更有效。因此,在使用迭代加深之前,需要评估其适用性和效果。

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

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

相关文章

Vue中的数据变化监控与响应——深入理解Watchers

目录 ​编辑 前言 1. 基本用法&#xff1a; 2. 深度监听&#xff1a; 3. 立即执行&#xff1a; 4. 监听多个数据&#xff1a; 5. 清理监听器&#xff1a; 6. 监听路由变化&#xff1a; 总结&#xff1a; 我的其他博客 前言 在Vue.js中&#xff0c;watch是一种用于监听…

Kafka本地安装⭐️(Windows)并测试生产消息以及消费消息的可用性

2023.12.17 天气晴 温度较低 十点半&#xff0c;不是不想起实在是阳光浴太nice了日常三连&#xff0c;喂&#xff0c;刷&#xff0c;肝刷会儿博客&#xff0c;看会儿设计模式冷冷冷 进被窝 刷视频 睡觉看看kafka的本地部署 》》实践》》成功写会儿博客&#xff0c…

Web前端-HTML(表格与表单)

文章目录 1.表格与表单1.1 概述 2.表格 table2.1 表格概述2.2. 创建表格2.3 表格属性2.4. 表头单元格标签th2.5 表格标题caption&#xff08;了解&#xff09;2.6 合并单元格(难点)2.7 总结表格 3. 表单标签(重点)3.1 概述3.2 form表单3.3 input 控件(重点)type 属性value属性值…

Android 蓝牙BluetoothAdapter 相关(一)

Android 蓝牙相关 本文主要讲述android 蓝牙的简单使用. 1: 是否支持蓝牙 /*** 是否支持蓝牙** return*/ private boolean isSupportBluetooth() {BluetoothAdapter bluetoothAdapter BluetoothAdapter.getDefaultAdapter();return bluetoothAdapter ! null; }2: 开启蓝牙 …

Java之Clonable接口和深浅拷贝

Clonable接口 我们船舰了一个人的对象&#xff0c;想要克隆一个一模一样的对象&#xff0c;可以用到object类里面的克隆方法 object不是所有类的父类吗&#xff1f;那为什么用person1点不出这个方法呢&#xff1f;可以看一下源码 这是Object类里面的clone方法的声明&#xff0…

HackTheBox-Machines--Analytics

文章目录 1 端口扫描2 测试思路3 漏洞探测4 权限获取5 权限提升 Analytics 测试过程 1 端口扫描 nmap -sC -sV 10.129.205.1422 测试思路 目标服务器只开启了80端口&#xff0c;所以出发点从80端口开始。对于web页面&#xff0c;能做的大致思路有&#xff1a; 1.目录扫描   2…

干货下载丨不分业态、不关注核心需求,怎么做得好项目管理?!

项目管理&#xff1a;装备制造业的破局利刃 对于装备制造行业而言&#xff0c;每一笔订单都是非标定制、小批量制造。这种特性决定了其行业企业普遍存在新品开发周期长、生产效率低、质量不稳定、交货期不稳定、成本预算难控制、非标品报价慢等问题。 如何提升企业的管理水平…

国产or进口?台阶仪为何要选择国产

在微观轮廓测量领域&#xff0c;选择一款合适的台阶仪对于获得精准的测量结果至关重要。随着科技的不断发展&#xff0c;台阶仪市场上涌现了许多国产和进口产品&#xff0c;消费者在选择时可能会面临一些疑虑。 什么是台阶仪 台阶仪是一种超精密接触式微观轮廓测量仪&#xf…

桌面概率长按键盘无法连续输入问题

问题描述&#xff1a;概率性长按键盘无法连续输入文本 问题定位&#xff1a; 系统按键流程分析 图一 系统按键流程 按键是由X Server接收的&#xff0c;这一点只要明白了X Window的工作机制就不难理解了。X Server在接收到按键后&#xff0c;会转发到相应程序的窗口中。在窗…

助力智能人群检测计数,基于YOLOv5全系列模型【n/s/m/l/x】开发构建通用场景下人群检测计数识别系统

在一些人流量比较大的场合&#xff0c;或者是一些特殊时刻、时段、节假日等特殊时期下&#xff0c;密切关注当前系统所承载的人流量是十分必要的&#xff0c;对于超出系统负荷容量的情况做到及时预警对于管理团队来说是保障人员安全的重要手段&#xff0c;本文的主要目的是想要…

SpringIOC之作用域Scope

博主介绍:✌全网粉丝5W+,全栈开发工程师,从事多年软件开发,在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战,博主也曾写过优秀论文,查重率极低,在这方面有丰富的经验✌ 博主作品:《Java项目案例》主要基于SpringBoot+MyBatis/MyBatis-plus+…

设计模式之创建型设计模式(一):单例模式 原型模式

单例模式 Singleton 1、什么是单例模式 在软件设计中&#xff0c;单例模式是一种创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点。 这意味着无论何时需要该类的实例&#xff0c;都可以获得相同的实例&#xff0c;而不会创建…

使用VBA快速统计词组词频(多单词组合)(2/2)

实例需求&#xff1a;产品清单如A列所示&#xff0c;现在如下统计多单词组合词组词频。 在上一篇博客中《使用VBA快速统计词组词频(多单词组合)&#xff08;1/2&#xff09;》讲解了如何实现双词的词频统计。 本文将讲解如何实现3词的词频统计&#xff0c;掌握实现方法之后&a…

Mac如何安装stable diffusion

今天跟大家一起在Mac电脑上安装下stable diffusion&#xff0c;在midjourney等模型收费的情况下如何用自己的电脑算力用上免费的画图大模型呢&#xff1f;来吧一起实操起来 一、安装homebrew 官网地址&#xff1a;Homebrew — The Missing Package Manager for macOS (or Lin…

SQL进阶理论篇(十):数据库中的锁

文章目录 简介按照锁的粒度进行划分从数据库管理的角度进行划分从程序员的角度进行划分为什么共享锁会发生死锁&#xff1f;参考文献 简介 索引和锁&#xff0c;是数据库中的两个核心知识点。 索引的相关知识点&#xff0c;在之前的几章里我们已经介绍的差不多了。接下来我们…

[pasecactf_2019]flask_ssti proc ssti config

其实这个很简单 Linux的/proc/self/学习-CSDN博客 首先ssti 直接fenjing一把锁了 这里被加密后 存储在 config中了 然后我们去config中查看即可 {{config}} 可以获取到flag的值 -M7\x10wd94\x02!-\x0eL\x0c;\x07(DKO\r\x17!2R4\x02\rO\x0bsT#-\x1cZ\x1dG然后就可以写代码解…

MNIST内置手写数字数据集的实现

torchvision库 torchivision库是PyTorch中用来处理图像和视频的一个辅助库&#xff0c;接下来我们就会使用torchvision库加载内置的数据集进行分类模型的演示 为了统一数据加载和处理代码&#xff0c;PyTorch提供了两个类用于处理数据加载&#xff0c;他们分别是torch.utils.…

机器视觉技术与应用实战(开运算、闭运算、细化)

开运算和闭运算的基础是膨胀和腐蚀&#xff0c;可以在看本文章前先阅读这篇文章机器视觉技术与应用实战&#xff08;Chapter Two-04&#xff09;-CSDN博客 开运算&#xff1a;先腐蚀后膨胀。开运算可以使图像的轮廓变得光滑&#xff0c;具有断开狭窄的间断和消除细小突出物的作…

饥荒Mod 开发(十五):小地图显示物品

饥荒Mod 开发(十四)&#xff1a;制作屏幕弹窗 本篇源码 饥荒中按下Tab键可以显示地图&#xff0c;刚开始进入游戏的时候地图是未探索状态&#xff0c;所以我们并不知道地图上面的物品分布情况。并且地图上只会显示很少一部分的物品&#xff0c;比如树枝&#xff0c;草&#xf…

C++二维数组(4)

蛇形遍历 题目描述&#xff1a;用数字1,2,3,4,...,n*n这n2个数蛇形填充规模为n*n的方阵。 蛇形填充方法为&#xff1a; 对于每一条左下-右上的斜线&#xff0c;从左上到右下依次编号1,2,...,2n-1&#xff1b;按编号从小到大的顺序&#xff0c;将数字从小到大填入各 条斜线&…