紧接着我们要再往前迈出一大步, 目的是要把生成器这个东西究竟是怎么运作的, 还有咱们应当怎样去定义它, 这些都清清楚楚地弄明白。[]如上所说, 生成器是其中一种类型特别的函数, 这个函数不返回单个数值, 不过它返回一个迭代对象的实例, 在生成器的函数体里面, 返回值这里采用的方式是那个yield的那个语句, 并非是一般意义上的语句, 以下就定义一个简易的生成器的功能函数, 具体的代码展现为下面的清单格式。这是代码清单当中的一部分片段内容, 编号为01。咱们在那份清单里面, 定下了一个作为生成器的函数来用。这个函数在执行的时候, 用的不是那个关键字, 而是用了yield语句。就是因为有了这个yield语句的存在, 所以, 它这才变成了一个生成器。当我们将这个函数给进行调用的时候, 它就会把一个迭代器的对象给回来给我们去使用。接下来, 咱们再回头去看一下, 关于生成器是怎么被调用出来的。代码清单的片段, 是编号为02的那一部分。所谓调用生成器, 通常情况下是跟创建对象有着相似的性质, 具体操作就是去调用那个生成器函数, 然后再把它赋给一个变量。当程序被启动并运行之后, 它所输出的结果表现如下。First ItemItemLast Item[]根据规则可知, 这个生成器函数里面是不应当包含关键字的。为啥? 因为如果它万一碰巧包含了这些关键字的话, 语句就会把此函数给终止掉。这样一来, 也就没法去满足迭代器的那个要求了。眼下, 我们得依靠 for 循环来出手, 定义出一个更有实际使用价值的生成器。具体到这种例子里面, 我们要去建立一个生成器, 这个生成器会一直追踪、一直往下出列那种从数字零开始往后面数的序列数, 一直到达到设定的最大限值是为止。代码清单, 以下就是。这是一个关于代码清单的片段展示, 其编号标记为零三。运行该程序以后, 所得到的输出结果情况与如下的展示方式比较相像。在上面的那个列表里面, 我们定义了一个叫生成器的函数, 这个函数它是用来生成那些整数的, 也就是从零开始一直到你给我的那个数字为止。就像大家看到的那样, yield这个语句是放在一个for循环里面的。然后, 请大家务必注意一下, 变量n的值会按照顺序自动地存储起来, 每次去调用的时候就调用next()这个方法。有一点需要特别注意一下, 在定义一个生成器的时候, 其核心功能是通过yield语句来体现的, 这不是说生成器里面就不能有别的语句存在, 通常情况下, 会有一个返回非None值的语句被放置在生成器的末尾位置处, 这样做的目的是为了给可能出现异常的情况添加一些额外提示信息, 这样一来调用者就可以更好地处理这些异常情况了, 下面是具体的示例展示。这是代码清单里头的片段部分, 编号为04。当程序在运行过程中没有进行异常处理的时候, 得到的输出结果可能类似于如下所示的情况。99100大多数人在最后一次尝试时都会失败。文件在……, 第11行, 在这个地方。print(next(g))目前这个平台是不支持来生成那些大于100的大数字的, 所以用户需要注意一下。如果针对程序异常进行了捕捉处理操作, 那么最终的输出显示会变得更为清晰简洁, 建议大家亲自动手运行程序进行实验验证。生成器这个物件, 还有普通的函数这两个概念。如果一个函数当中至少包含了一个用于表示生成器含义的yield语句, 那么这个函数就会被认定为是一个生成器函数。在存在这种需求的情形之下, 该函数内部同样可以被安排有其他类型的yield内容或者是常规的逻辑语句。当进行执行操作时, yield关键词以及相关的内容结构均具备从所属函数的内部向外部传递并输出一些具体结果数据的能力与功能。和yield关键字之间的差异对于生成器来说非常重要。语句会完全终止函数。而yield语句会暂停函数。它会保存它的所有状态。然后在后续的调用中, 它会继续执行。我们在使用生成器函数的时候, 方法和调用普通函数的操作是一样的。不过, 在运行的过程中, 当代码运行到出现yield这个关键字的地方时, 生成器就会暂停下来。在这个时候, 它会把当前处于迭代流中的那个值发给正在调用的环境去使用。然后, 它就会开始等待, 直到下一次被再次调用为止。与此同时, 它还会在自己的内部把这个过程的局部变量还有它们的状态都保存好。这里列出来了一些关键点, 这些关键点把生成器函数和普通函数给区分开了, 让大家能够看清楚两者的不同之处。这个函数会返回一个用来进行迭代的数据对象。你完全不需要去担心必须亲自显式地把这个数据对象给创建出来, 因为有一个叫做关键字的东西叫作yield。正是这个关键字替你完成了该对象的创建工作。我们用一个简单的例子来演示普通函数和生成器函数之间的区别, 在这个例子中, 我们要计算前n个正整数的和, 为此, 我们将定义一个函数, 该函数给出前n个正数的列表, 我们将以两种方式实现这个函数, 一个是普通函数, 一个是生成器函数。普通函数代码如下这个片段是属于代码清单中的第05部分。运行程序输出结果类似如下Time in : 1.29404在代码清单这里, 我们要定义一个普普通通的函数, 这个函数的作用就是去返回前n个正整数的那些数字所组成的一个列表, 等到我们真正把这个函数拿去调用的时候它必须要花掉一段不短的时间才能把执行动作给完成掉, 这是因为它在干活的过程中所创建出来的那个列表实在是太过庞大了, 大到让人有点喘不过气来, 而且, 为了把这件事情给办成, 它同时也消耗掉了非常多的内存资源。现在的话, 就让我们来给那个相同的操作去定义一个生成器的函数, 好让它可以被实现出来, 具体的那个代码清单呢, 就是下面这个样子的:这个部分展示的是代码清单片段, 具体内容编号为06。运行程序结果类似如下这是生成器模式, 里面的时间数值是1.82764。就像我们在生成器清单里能看到的那样, 生成器能够在更短的时间内完成同样的任务, 并且消耗更少的内存资源。这是因为它是一个一个地产生项目, 而并不是返回完整的列表。我们要进行性能改进, 主要原因是什么呢? 原因在于值的惰性生成。具体点说, 就是当我们使用生成器的时候。所谓按需生成值, 这种方式是有明显效果的。它的效果就是会降低内存使用量。这还只是其中一个优点。另一个优点更值得注意。你根本不需要等待所有元素都生成完毕。你可以在需要的时刻直接使用它们。生成器表达式在现实情况里, 咱们确实时常得靠一些简简单单的生成器去做代码里头那种比较普通的活儿。这玩意儿就是生成器表达式该大展身手的地方了。咱们要是想动手变出一堆简单点的生成器出来, 直接用生成器表达式去动态搞一搞就行了, 挺方便的。生成器表达式类似于普通函数, 但是我们要记住的是匿名这个性质, 它允许我们动态地创建只有一行的函数内容。就像普通的函数一样, 生成器表达式所创建的其实也是匿名性质的生成器函数这一概念。那个生成器表达式的语法看着就像是一个列表推导式, 可不同的地方在于, 咱们在用那个生成器表达式的时候, 会把原本在列表推导式里会用到的那些方括号给换掉, 然后换成圆括号来用, 具体是个啥样子的情况, 大家可以瞧一下底下这个示例。最终的运行表现大致就像是下面这个样子。在上面那个清单里面呢, 我们借助生成器表达式帮忙, 定义了一个挺简单的生成器。下面的内容是关于语法的信息: 等于号后面跟着左括号, 然后是i立方, 接着是for循环针对nums, 最后用右括号闭合, 也就是(i3 for i in nums)。你可以在输出结果那里看到生成器对象。正如同大家已经知道的那样, 为了能够在这个生成器里去拿到里面的项, 咱们要么选择显式调用next()这种方法, 要么使用for循环来把生成器进行遍历。接下来的内容就关于打印对象中所包含的项了, 具体的情况如下进行展示:当你去执行那个程序的以后, 你所看到的那些被遍历出来的元素项的最终结果, 是否真的会和由列表推导式所生成的结果保持一致呢。我们再看看另外一个例子, 具体就是创建一个生成器函数, 让这个函数的功能是把字符串当中的每一个字母都变成大写形式, 接下来再去调用那个名为 next 的方法并且输出最前面的两个字符对应的内容, 相关的代码样本展示在下面这个位置。程序的运行结果输出在了屏幕上面, 具体情况如下所示:生成器好处生成器是极为出色的工具, 尤其在需要于相对有限的内存空间内处理庞大体积的数据之时, 其优势便凸显出来。下面将列举在应用过程中使用生成器所涉及的一些核心益处。1内存效率:咱们假如遇到了一个普通函数, 这个函数的返回值会是一个特别大的序列。举个例子来说, 这个序列可能包含数百万项的数据。要是你调用这个函数, 你就得硬着头皮等它把所有的代码都执行完, 然后才能把整个列表交到你手里。在时间和内存这两种资源的使用效率上面来看, 这种做法显然太低效了。换个角度讲, 如果你改用生成器函数来处理问题, 那么它就会一项接一项地把结果返回给你。这样的话, 你就有机会去继续执行后面的代码行。你根本不需要干巴巴地等着函数把那个列表里的所有项全部处理完毕, 这省了很多事。因为生成器一次性只给你一项。2延迟计算:生成器这个工具, 它提供了一个可以延迟进行计算的求值功能。这个延迟计算是个啥意思? 也就是说, 它在真正需要那个值的时候, 才去计算那个值, 而不是在一开始实例化的时候就把值给算出来。假设你手头有一个特别大的数据集, 需要去计算它里面的东西, 那么, 如果你用延迟计算的方法的话, 它就允许你在整个数据集还在一步步计算生成的过程中, 你就可以立即开始使用那些已经出来的数据了。这是为啥, 这是因为如果使用生成器的话, 你就根本不需要等到整个数据集全部计算完, 也就不存在需要整个数据集的情况。3实现起来比较方便, 而且阅读和理解起来也容易。生成器的实现过程是非常轻松的, 而且它能够提供非常良好的代码可读性大家需要记住的是, 一旦选择使用生成器这一技术手段, 你就完全不需要去担心有关那两个括号的特定方法该如何处理, 在函数内部仅仅安排一个非常基础的生成关键字的使用语句, 这就足够满足所有需求了。4对无限流这一题材进行处理。当你遇到需要表现那种无限流淌下去的数据序列这种状况时, 生成器就变成了一种特别有用的好工具。比如, 我们可以构建出一个永远都在增加数字的无限计数器。从理论层面来说, 你根本没法在计算机内存当中把这样无限的流程全部存下来, 原因是你完全搞不清楚存储这么大没边界的流程究竟会需要消耗掉多大规模的内存空间。这正是生成器真正能够大展拳脚的关键所在的地方, 因为它每次只负责制造并吐出那唯一的、单独的一项内容。所以它完全有能力去代表那些无穷无尽的数据流, 而且这个过程里头, 它绝对不会把所有的所有数据流一股脑儿全都堆积塞进内存里面去。本文小结主要内容是介绍了生成器相关的知识, 目的是为了能够更好的自定义迭代器。文中包括了以下几个问题。一个是关于什么叫做生成器。第二个是如何去自定义生成器, 以及它和普通函数的关键区别是什么。第三个是为了如何实现生成器的表达式。最后还总结了生成器的优点。相信通过阅读这篇文章, 你会更轻松且更高效地掌握常规生成器方面的内容。
企业数字化 ERP 产品动态
相关推荐
纯静态HTML发布页:零依赖、高可用、可审计的轻量服务入口设计 1. 什么是纯静态HTML地址发布页?它为什么值得你花30分钟认真读完纯静态HTML地址发布页,不是那种“打开就弹窗广告、加载三秒才出文字”的老式企业官网首页,也不是用Vue或React打包出来的单页应用。它是一份完全不依赖后端服务、数据库、运行时… · 2026/9/26 12:31:28
短期负荷预测与网络重构:主动配电网IEEE33节点优化实践 主动配电网短期负荷预测与网络重构优化这个课题,我在实验室里断断续续做了四个多月。最直观的感受是:算法本身并不是最大的门槛,真正磨人的是把“预测出来的负荷曲线”和“IEEE33节点系统的重构优化”这两件事严丝合缝地接起来。这篇文章想把… · 2026/9/26 12:31:28
从0到1搭建AI Agent平台:造同事思维与落地方案 1. “造同事”这件事,第一步不是选框架,而是换思维1.1 同事和工具的本质区别我看到这个标题的第一反应,不是“又有人来蹭 Agent 热点了”,而是觉得“造同事”这三个字,其实把 AI Agent 这件事说透了。过去我们做软件&a… · 2026/9/26 12:31:22
金融后端系统实战:账务、风控与高可用架构设计 1. 从“financial-services”这个标题里,我读出了什么“financial-services”这个标题看起来简单,甚至有点过于宽泛,但它恰恰是那种最考验拆解能力的题目。没有项目正文,没有关键词,没有摘要描述,只有一个孤… · 2026/9/26 13:10:51
MCP工具接入生产环境:权限、超时与审计的实战指南 1. 从“能调用”到“敢上线”:MCP 工具接入的真实门槛很多人第一次把 MCP 工具接进自己的 Agent 或者工作流时,心态都差不多:跑通了,能调用了,日志里看到工具返回结果了,就觉得这事成了。我一开始也是这么想… · 2026/9/26 13:10:45
优服家政上门疏通服务可以信任吗 镇江市京口区优服家政服务部是镇江市深耕本土的一站式民生维修服务品牌,核心提供管道疏通、水电维修、空调维修、防水补漏四大民生刚需服务,不提供保洁保姆服务,专注解决镇江本地家庭、商铺、小区、餐饮店的各类排水、用电、渗水、制冷故障问… · 2026/9/26 13:10:45
用Jev替换编码代理中的低速LLM调用,成本直降57% 前几天我把 coding agent 的月度账单拉出来看了一眼,心里一沉。整套 agent 系统一天要跑上千次 LLM 调用,其中相当一部分是那种“要不要都行”的轮次——修个 JSON 格式、补个类型标注、裁一下日志上下文。慢也就算了,token 消耗一点都不少。… · 2026/9/26 13:10:45
科学记忆方法论:基于遗忘曲线与间隔重复,告别看完就忘 在饭局上被人喊出名字却一脸茫然,在会议上被领导追问“上个月那个数据你还记得吗”时大脑直接宕机……这些瞬间我过去几乎每周都要经历一次。后来我认真研究了一个叫“科学记忆”的领域,才意识到问题不在脑子,而在我从没认真学过“怎么记”。… · 2026/9/26 13:10:45
复合铜线生产厂家排名哪家好?实力参考与用户口碑深度解析 选择靠谱的复合铜线供应商,从来都不是看榜单排名,而是看真实生产实力与用户实际口碑,只有匹配自身生产需求,才能帮企业降本增效,守住生产质量底线。很多采购朋友在寻找供应商的时候,都会有同样的疑问&#… · 2026/9/26 13:10:45
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46