专栏首页大数据入坑指南Python自学成才之路 迭代器的使用

Python自学成才之路 迭代器的使用

可迭代对象 实现了__iter__魔术方法的对象是可迭代对象(Iterable)

迭代器 实现了__iter__和__next__魔术方法的对象是迭代器(Iterator)

迭代器和可迭代对象的区别在于迭代器是可以通过for循环来遍历的,而可迭代对象如果没有实现__next__魔术方法是不能用for来遍历的。

判断一个对象是否是可迭代对象 使用isinstance()判断一个对象是否是Iterable

from collections import Iterable, Iterator
ret = isinstance([1, 2, 3], Iterable)
print(ret)

ret = isinstance((1, 2, 3), Iterable)
print(ret)

ret = isinstance("abc", Iterable)
print(ret)

ret = isinstance(123, Iterable)
print(ret)

输出:
True
True
True
False

创建一个迭代器 要求:实现__iter__()魔术方法并返回一个特殊的可迭代对象,这个可迭代对象需要实现 next() 方法并通过 StopIteration 异常标识迭代的完成。 咋一看可能不太懂什么意思,下面通过几个案例讲解下。

实现了__iter__()魔术方法的对象是一个可迭代对象,但是没法通过for循环进行遍历。

from collections import Iterable, Iterator

class MyRangeIterator(object):
    def __init__(self, start, end):
        self.index = start
        self.end = end

    def __iter__(self):
        return self


myrange = MyRangeIterator(1, 2)
print(isinstance(myrange, Iterable))

for x in myrange:
    print(x)
    
输出:
True
Traceback (most recent call last):
  File "D:/pycharm workspace/oopdemo/iterator_generator/IteratorDemo03.py", line 22, in <module>
    for x in myrange:
TypeError: iter() returned non-iterator of type 'MyRangeIterator'

这个MyRangeIterator对象实现了__iter__魔术方法,返回的是它自身实例,但是MyRangeIterator并没有实现__next__()魔术方法,所以没法使用for遍历,下面实现__next__魔术方法后就可以使用for遍历了。

class MyRangeIterator(object):
    def __init__(self, start, end):
        self.index = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < self.end:
            temp = self.index
            self.index += 1
            return temp
        else:
            raise StopIteration()

myrange = MyRangeIterator(1, 3)
print(isinstance(myrange, Iterable))

for x in myrange:
    print(x)
    
输出:
True
1
2

注意:在实现__next__魔术方法的时候,当遍历完成后需要抛出StopIteration异常,否则迭代过程不会停下来。 __next__魔术方法对应的是next()函数,所以上面的迭代器对象还可以这样使用。

print(next(myrange))

在使用for循环遍历的时候,内部其实是自动通过next函数来取值。

上面那种__iter__方法直接返回自身实例来实现迭代器的方式实际上有个坑,还是上面那个案例,如果使用两个for循环来遍历,第二个for循环遍历不到值。

myrange = MyRangeIterator(1, 3)
print(isinstance(myrange, Iterable))

for x in myrange:
    print(x)

for y in myrange:
    print(y)
输出:
True
1
2

第二个for循环没有值输出,原因是myrange这个实例的index值发生了变化,所以再使用for遍历的时候,index已经达到最大值了,不会再取到值。所以实现迭代器最好的方法是每次都返回一个迭代器实例,像下面这样。

class MyRangeIterator(object):
    def __init__(self, start, end):
        self.index = start
        self.end = end

    def __iter__(self):
        return self

    def __next__(self):
        if self.index < self.end:
            temp = self.index
            self.index += 1
            return temp
        else:
            raise StopIteration()


class MyRange(object):

    def __init__(self, start, end):
        self.start = start
        self.end = end

    def __iter__(self):
        return MyRangeIterator(self.start, self.end)


ret = MyRange(1, 3)
for x in ret:
    print(x)
print("="*10)
for y in ret:
    print(y)
输出:
1
2
==========
1
2

这个例子中MyRange没有实现__next__方法,而是在__iter__魔术方法中返回了一个实现了__next__的可迭代对象。所以它也是一个迭代器对象,而且每次使用for遍历的时候都会通过__iter__返回一个新的MyRangeIterator实例。

其实文章开头对迭代器的定义有点不准确,实际还可以通过生成器的方式来得到迭代器,下一节会介绍生成器!

本人是做大数据开发的,在微信上开了个个人号,会经常在上面分享一些学习心得,原创文章都会首发到公众号上,感兴趣的盆友可以关注下哦!

大数据入坑指南

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python自学成才之路 分布式计算解决方案actor

    以下内容来自于cookbook,个人觉得这篇文章对于设计分布式计算任务有一定的借鉴意义,感兴趣的同学可以阅读原文: https://python3-cookb...

    我是李超人
  • python自学成才之路 列表,元组,集合详细用法

    python列表使用[]表示,它实际上是一个数组,但是和一般数组不同的地方在于它内部封装了很多很好用的方法(比如append,pop)以及一些特性(比如切片,不...

    我是李超人
  • Python自学成才之路 魔术方法之一元,二元运算符

    一元运算符有+,-,~等,要想使这些一元运算符对对象起作用,需要在定义类的时候实现对应的魔术方法。

    我是李超人
  • python的迭代对象

    迭代对象这个概念是python里面非常核心的东西,我想跟大家分享一下,什么是可迭代对象。

    stormwen
  • Python 强化训练:第三篇

    谢伟
  • Antd Vue的MonthPicker组件不能用,提示注册的解决方法

    项目中需要用到 Ant Design 的 MonthPicker 月份组件,但是不能用,引入后组件不能正常显示,控制台报错: vue.esm.js?efeb:6...

    德顺
  • HDU 4135 Co-prime(容斥原理)

    Co-prime Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ...

    ShenduCC
  • python3实现excel里面读数据进

    py3study
  • 使用卷积深度神经网络和PyTorch库对花卉图像进行分类

    语言图像数据是深度学习技术的一种非常流行的用法。在本文中将讨论使用深度卷积神经网络识别花卉图像。

    代码医生工作室
  • Rust Async: smol源码分析-Executor篇

    本文来自知乎:https://zhuanlan.zhihu.com/p/137353103

    MikeLoveRust

扫码关注云+社区

领取腾讯云代金券