返回介绍

有多个迭代器的对象

发布于 2024-01-29 22:24:15 字数 1653 浏览 0 评论 0 收藏 0

之前,提到过迭代器对象可以定义成一个独立的类,有其自己的状态信息,从而能够支持相同数据的多个迭代。考虑一下,当步进到字符串这类内置类型时,会发生什么事情。

在这里,外层循环调用iter从字符串中取得迭代器,而每个嵌套的循环也做相同的事来获得独立的迭代器。因为每个激活状态下的迭代器都有自己的状态信息,而不管其他激活状态下的循环是什么状态。

我们前面在第14章和第20章看到了相关的例子。例如,生成器函数和表达式,以及map和zip这样的内置函数,都证明是单迭代对象;相反,range内置函数和其他的内置类型(如列表),支持独立位置的多个活跃迭代器。

当我们用类编写用户定义的迭代器的时候,由我们来决定是支持一个单个的或是多个活跃的迭代。要达到多个迭代器的效果,__iter__只需替迭代器定义新的状态对象,而不是返回self。

例如,下面定义了一个迭代器类,迭代时,跳过下一个元素。因为迭代器对象会在每次迭代时都重新创建,所以能够支持多个处于激活状态下的循环。

运行时,这个例子工作起来就像是对内置字符串进行嵌套循环一样,因为每个循环都会获得独立的迭代器对象来记录自己的状态信息,所以每个激活状态下的循环都有自己在字符串中的位置。

作为对比,除非我们在嵌套循环中再次调用Squares来获得新的迭代对象,否则之前的Squares例子只支持一个激活状态下的迭代。在这里,只有SkipObject,但从该对象中创建了许多的迭代器对象。

就像往常一样,我们可以用内置工具达到类似的效果。例如,用第三参数边界值进行分片运算来跳过元素。

然而,这并不完全相同,主要有两个原因。首先,这里的每个分片表达式,实质上都是一次把结果列表存储在内存中;另一方面,迭代器则是一次产生一个值,这样使大型结果列表节省了实际的空间。其次,分片产生的新对象,其实我们没有对同一个对象进行多处的循环。为了更接近于类,我们需要事先创建一个独立的对象通过分片运算进行步进。

这样与基于类的解决办法更相似一些,但是,它仍是一次性把分片结果存储在内存中(目前内置分片运算并没有生成器),并且只等效于这里跳过一个元素的特殊情况。

因为迭代器能够做类能做的任何事,所以它比这个例子所展示出来的更通用。无论我们的应用程序是否需要这种通用性,用户定义的迭代器都是强大的工具,可让我们把任意对象的外观和用法变得很像本书所遇到过的其他序列和可迭代对象。例如,我们可将这项技术在数据库对象中运用,通过迭代进行数据库的读取,让多个游标进入同一个查询结果。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文