前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你所不知道的Python迭代器

你所不知道的Python迭代器

作者头像
蒙娜丽宁
发布2020-04-13 12:49:46
3890
发布2020-04-13 12:49:46
举报
文章被收录于专栏:极客起源

迭代就是循环的意思,也就是对一个集合中的元素进行循环,从而得到每一个元素。对于我们自定义的类,也可以让其支持迭代,这就是本文要介绍的特殊成员方法__iter__的作用。用该成员方法可以自定义一个Python迭代器

1 自定义可迭代的类

可能有的读者会问,为什么不使用列表呢?列表可以获取列表的长度,然后使用变量i对列表索引进行循环,不照样可以获取集合的所有元素吗,还容易理解。没错,使用列表的代码是容易理解,也很好操作,但这是要付出代价的。列表之所以可以用索引来快速定位其中的任何一个元素,是因为列表是一下子将所有的数据都装载的内存中了,而且是一块连续的内存空间。如果数据量比较小还好说,如果数据量很大的话,会非常消耗内存资源。而迭代就不同,迭代是读取多少元素,就将多少元素装载到内存中,不读取就不装载。这有点像处理XML的两种方式:DOM和SAX。DOM是一下子将所有的XML数据都装载到内存中,所以可以快速定位任何一个元素,但代价是消耗内存,而SAX是顺序读取XML文档,没读到的XML文档内容是不会装载到内存中的,所以SAX比较节省内存,但只能从前向后顺序读取XML文档的内容。

如果在一个类中定义__iter__方法,那么这个类的实例就是一个迭代器。__iter__方法需要返回一个迭代器,所以就返回对象本身即可(也就是self)。当对象没迭代一次时,就会调用迭代器中的另外一个特殊成员方法__next__。该方法需要返回当前迭代的结果。下面让我们先看一个简单的例子,在这个例子中,通过自定义迭代器对由星号(*)组成的直角三角形的每一行进行迭代,然后通过for循环进行迭代,输出一定行数的直角三角形。

代码语言:javascript
复制
# 可无限迭代直角三角形的行class RightTriangle:def __init__(self):    # 定义一个变量n,表示当前的行数        self.n = 1def __next__(self):           # 通过字符串的乘法获取直角三角形每一行的字符串,每一行字符串的长度是2 * n - 1        result = '*' * (2 * self.n - 1)        # 行数加1        self.n += 1        return result    # 该方法必须返回一个迭代器    def __iter__(self):        return selfrt = RightTriangle()# 对迭代器进行迭代for e in rt:     # 限制输出行的长度不能大于20,否则会无限输出行    if len(e) > 20:        break;    print(e)

程序运行结果如下图所示。

2. 将迭代器转换为列表

尽管迭代器很好用,但仍然不具备某些功能,例如,通过索引获取某个元素,进行分片操作。这些操作都是列表的专利,所以在很多时候,需要将迭代器转换为列表。但有很多迭代器都是无限迭代的,就像上一节中的斐波那契数列的迭代。因此,在将迭代器转换为列表时,需要给迭代器能够迭代的元素限定一个范围,否则内存就会溢出了。如果要让迭代器停止迭代,只需要抛出StopIteration异常即可。通过list函数可以直接将迭代器转换为列表。

下面的代码会将斐波那契数列迭代器通过list函数转换为列表。斐波那契数列迭代器限制了最大迭代值不能超过500。

代码语言:javascript
复制
# 将迭代器转换为列表class Fibonacci:    def __init__(self):        self.a = 0        self.b = 1    def __next__(self):        result = self.a        self.a, self.b = self.b, self.a + self.b        # 要想让迭代停止,需要抛出StopIteration异常        if result > 500: raise StopIteration        return result    def __iter__(self):        return self fibs1 = Fibonacci()# 将迭代器转换为列表print(list(fibs1))fibs2 = Fibonacci()# 使用for循环对迭代器进行迭代for fib in fibs2:    print(fib, end = ' ')

程序运行结果如图下图所示

从上面的代码可以看出,尽管在__next__方法中,当result大于500时抛出了StopIteration异常,但这个异常是在迭代的过程中由系统处理的,并不会在程序中抛出,所以如果要将无限迭代改成有限迭代,可以在适当的时候抛出StopIteration异常。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 极客起源 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档