python中for..in语法的原理?

news2024/12/23 20:48:51

今天发现了python中一个比较有意思的小设计。

如果要通过中括号[]访问元素,需要重写__get__item()函数,这个应该没什么疑问,测试代码如下:

class Classroom:
    def __init__(self, students):
        self.students = students

    def __getitem__(self, sid):
        for s in self.students:
            if s.sid == sid:
                return s

    def __len__(self):
        return len(self.students)


class Student:
    def __init__(self, sid, name):
        self.sid = sid
        self.name = name

    def __repr__(self):
        return str.format("sid: {}, name: {}", self.sid, self.name)


if __name__ == '__main__':
    class_room = Classroom([Student(12, "小明"), Student(13, "小华")])
    print(class_room[12])

通过中括号加学号的方式,可以获得对应学号的学生,代码顺利执行,没问题。

在我想要用for...in迭代时

if __name__ == '__main__':
    class_room = Classroom([Student(12, "小明"), Student(13, "小华")])
    for student in class_room:
        print(student)

出现了问题,进入了死循环,控制台打印出迭代到的值一直是None

当我换一种写法时,就可以遍历成功了

但这么做有个问题,sid就不是学号了,而是students数组的下标,这和业务的语义是不相符的。但是我们先不忽略这一点,研究下for in到底是怎么实现的。

以Java为例,需要通过迭代器来迭代集合元素,集合元素通过next()方法获取元素,通过hasNext()方法探测迭代的终点。

那么python是如何只通过一个函数就能实现迭代的呢?

先说结论:从下标0开始迭代,直到__getitem__函数抛出IndexError异常。

for in刚开始迭代时,固定给getitem函数传了0,随后从0开始递增。

如果判断正确,students[sid],在迭代三次后,应该会抛出数组越界的异常IndexError,所以我怀疑可能是解释器把捕捉到IndexError异常作为了迭代终止的条件。(经过测试,只有IndexError会正常退出循环,其他类型的异常会直接显示报错)

 修改代码,在第10次循环时,抛出异常

果然循环停止了,控制台打印结果:

再补充一点,通过iter函数以及next函数来迭代时,最终也是调用了getitem方法,下标也是从0开始。

if __name__ == '__main__':
    class_room = Classroom([Student(12, "小明"), Student(13, "小华")])
    # for student in class_room:
    #     print(student)

    stu_iter = iter(class_room)
    print(next(stu_iter))
    print(next(stu_iter))
    print(next(stu_iter))

 

如有错误,欢迎指正。

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

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

相关文章

为什么程序员每到一家新公司干了两三年,都有一种干不下去的感觉?

行业内有句话叫:“程序员跳一次等于干三年”。但是程序员这个岗位怎么说呢? 小伙伴都知道的,工作强度完全看运气,有的公司忙到头都秃了,也有的公司闲到抠脚。 而收入呢?在一家公司待着,基本上是万年不涨的…

【C语言初阶(19)】实用的 VS 调试技巧

文章目录 Ⅰ 调试的介绍Ⅱ 常用调试快捷键Ⅲ 调试的时候查看程序当前信息⒈查看临时变量的值⒉查看内存信息⒊查看调用堆栈⒋查看汇编信息⒌查看寄存器信息 Ⅳ 观察形参指针指向的数组Ⅴ 易于调试的代码该如何编写⒈const 修饰指针变量⒉良好代码示范 Ⅵ 编程中常见的错误 Ⅰ 调…

Mr. Cappuccino的第54杯咖啡——Mybatis运行原理

Mybatis运行原理 Mybatis运行的三个阶段Mybatis运行原理图 Mybatis运行的三个阶段 初始化阶段:读取并解析XML配置文件和注解中的配置信息,创建配置对象,并完成各个模块的初始化工作,底层采用建造者模式;代理封装阶段&…

Qt、C/C++环境中内嵌LUA脚本、实现LUA函数的调用执行

Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行 Chapter1. Qt、C/C环境中内嵌LUA脚本、实现LUA函数的调用执行1、LUA简介2、LUA脚本的解释器和编译器3、C环境中内嵌LUA执行LUA函数调用4、Qt内嵌LUA执行LUA函数调用5、运行结果6、内嵌LUA脚本在实际项目中的案例应用 Chapter1…

元宇宙是概念炒作?

关键字:万界星空、万界星空科技、工业元宇宙、AR数字孪生、工业数字孪生、汽车数字孪生、机械加工数字孪生 引言 近两年被“元宇宙”席卷了,好多人问也好多人在各大媒体讨论过:“元宇宙到底是个啥?” 想必你也一定有所耳闻&…

世界少棒经典赛·棒球1号位

世界少棒经典赛 1. 世界少棒经典赛的起源 详细描述世界少棒经典赛的历史起源。 世界少棒经典赛的历史起源可以追溯到1985年,那个夏天,它首次在美国新泽西州举行,那时只有来自美国的12支球队参赛,这些球队在当地的特伦顿市体育中…

meanshift算法通俗讲解【meanshift实例展示】

meanshift算法原理 meanshift算法的原理很简单。假设你有一堆点集,还有一个小的窗口,这个窗口可能是圆形的,现在你可能要移动这个窗口到点集密度最大的区域当中。 如下图: 最开始的窗口是蓝色圆环的区域,命名为C1。蓝…

【Linux命令200例】split将一个大文件拆分成多个小文件

🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主✌,2023年6月csdn上海赛道top4✌。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加…

Java多线程(四)

目录 一、线程的状态 1.1 观察线程的所有状态 1.2 线程状态和状态转移的意义 1.2.1 NEW、RUNNABLE、TERMINATED状态转换 1.2.2 WAITING、BLOCKED、TIMED_WAITING状态转换 1.2.3 yield()大公无私让出cpu 一、线程的状态 1.1 观察线程的所有状态 public class Demo9 {public st…

HTML5网页设计小案例:网页导航栏的设计

什么是导航栏,按我的理解就是位于网页顶部或者侧边一组链接或者按钮,用来指导大家找到网页的不同板块,大家可以一目了然的找到自己想看的板块内容。今天我们设计一个位于网页顶部的的导航栏。按我的生活经验来说,网页的顶部导航栏…

人机融合意识与人类的意识的区别

人机融合意识是指人类与计算机系统之间建立起密切的交互和协作关系,形成一种共同的意识和认知状态。人机融合意识与人类意识存在一些本质上的区别,可以从以下几个方面进行区分: 原始性:人类的意识是自然生命的产物,伴随…

怎样在Apipost中设计出实用又好看的API文档

Apipost一直推荐文档先行的API设计理念,在Apipost中可以添加Markdown格式的文本,用以储备文档和API文档设计。 作为一种轻量级标记语言,Markdown在撰写文档、博客文章、README文件以及网站内容上被广泛使用。 如何在Apipost中设计出漂亮的文…

在coopeliasim中打开场景对象属性的三种方式

一、点击[Menu bar --> Tools --> Scene object properties] 二、点击界面左侧按钮 三、双击场景层次结构中的对象图标

堆、堆栈、栈、堆和栈这些概念你还分的清楚吗?

数据结构中的堆、栈和队列 堆:堆是一种经过排序的树形数据结构,每个结点都有一个值。通常我们所说的堆的数据结构,是指二叉堆。堆的特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。由于堆的…

TDosCommand 组件来执行 JavaScript 脚本(nodejs)

可以在 Delphi 中使用 TDosCommand 组件来执行 JavaScript 脚本。但是,由于 JavaScript 是一种脚本语言,它通常在浏览器中运行,因此您需要使用一种 JavaScript 引擎来执行 JavaScript 脚本。常见的 JavaScript 引擎有 Node.js、Rhino、V8 等等…

定档!WAVE SUMMIT 2023@全球开发者,8月16日北京见!

潮汐涌动时,变化悄然发生。2023年全球AI浪潮迭起,大语言模型热度空前,生成式人工智能为千行百业高质量发展带来更多想象空间,一个蓬勃创新、重构万物的“大模型时代”正蓄势待发。 滴滴滴~飞桨全球开发者,…

CMIP6数据处理教程

详情点击链接:CMIP6数据处理及在气候变化、水文、生态等领域中的应用教程 一:CMIP6中的模式比较计划 1.1 GCM 全球气候模型(Global Climate Model, GCM),也被称为全球环流模型或全球大气模型,是一种用于…

科研周报1

时间:2023-07-26至2023-08-02 overleaf (LaTex) 生成并排子图 查看以下这段与chatgpt的对话: https://chat.openai.com/share/e7fbdccd-2847-4dbb-b816-db2b7455c628 如果要生成上下排列的子图,将\hfill更换为\即可 其他 前馈控制 参考…

Edge浏览器安装vue devtools

1. 下载地址 GitHub - vuejs/devtools: ⚙️ Browser devtools extension for debugging Vue.js applications. 2. 下载后的压缩包解压并打开文件夹,右键选择:git bush here 3. 安装依赖 npm install 4. 成功安装依赖后打包 npm run build

自动化测试中的数据驱动

DDT 当测试框架是unittest时,可以使用ddt。ddt 这个类装饰器必须装饰在 TestCase 的子类上,TestCase 是 unittest 框架中的一个基类,它实现了 Test Runner 驱动测试运行所需的接口(interface)。 DDT 的使用步骤如下&…