Python 之可迭代对象与迭代器

  什么是可迭代对象?
  答,有_iter_()函数的对象就成为可迭代对象。如果你再追问:iter()函数有什么用?那告诉你,像for循环就是一个框架协议,就是靠着使用_iter_()来实现的。所以弄懂_iter_()有什么用,就是弄懂for循环在底层干什么事情弄懂for循环原理的过程。
  下面举例说明,如果我们有一个自定义的类想使用for遍历它,代码中所示:

"""
    类:技能类,作用暂时不写
"""

class Skill:
    def __init__(self):
        pass
"""
    类:技能管理类
    作用:管理技能,包括对类的增加、访问
"""

class SkillManage:
    def __init__(self):
        self._skills = []
    def add_skill(self,skill):
        self._skills.append(skill)

m01 = SkillManage()
m01.add_skill(Skill())
m01.add_skill(Skill())
m01.add_skill(Skill())
for m001 in m01:
    print(m01)

输出:

File "C:/Users/ZBZ/PycharmProjects/untitled/iter_analyse.py", line 23, in <module>
    for m001 in m01:
TypeError: 'SkillManage' object is not iterable

如图错误提示,错误类型为类型不是可迭代的。那么我们就按照可迭代对象的定义给我们的自定义类添加_iter_()方法。

"""
    类:技能类,作用暂时不写
"""

class Skill:
    def __init__(self,name):
        self.name = name
"""
    类:技能管理类
    作用:管理技能,包括对类的增加、访问
"""

class SkillManage:
    def __init__(self):
        self._skills = []
    def add_skill(self,skill):
        self._skills.append(skill)
    def __iter__(self):
        return SKillIterator(self._skills)
"""
    类:迭代器
"""
class SKillIterator:
    def __init__(self,target):
        self.__skills = target
        self.__index = 0
    def __next__(self):
        if(self.__index == len(self.__skills)):
            raise StopIteration
        temp = self.__skills[self.__index]
        self.__index += 1
        return temp
m01 = SkillManage()
m01.add_skill(Skill("打狗棒法"))
m01.add_skill(Skill("御女心经"))
m01.add_skill(Skill("降龙十巴掌"))

for m0 in m01:
    print(m0.name)

  改成这样就可以使用for,表示可迭代了。其中主要的改动就是在SKillManage中添加_iter_()函数,在其中返回迭代器。那么又添加了一个迭代器类,迭代器中要有_next_()方法,返回一个对象,并且记录返回的索引,当集合中所有的对象都已经返回一遍后要记得停止。
  这个就是迭代器思想,next()方法执行一次,返回下一个对象。然后迭代器的实现原理或者说本质就是上面的做法,我们可以借助yield来自动生成迭代器的类,代码改为如下:

"""
    类:技能类,作用暂时不写
"""

class Skill:
    def __init__(self,name):
        self.name = name
"""
    类:技能管理类
    作用:管理技能,包括对类的增加、访问
"""

class SkillManage:
    def __init__(self):
        self._skills = []
        self._index =0
    def add_skill(self,skill):
        self._skills.append(skill)
    def __iter__(self):
        while self._index < len(self._skills):
            # yield 作用: 将下列代码改为迭代器模式的代码.
            # 生成迭代器代码的大致规则:
            # 1. 将yield以前的语句定义在next方法中
            # 2. 将yield后面的数据作为next方法返回值
            yield self._skills[self._index]
            self._index += 1
m01 = SkillManage()
m01.add_skill(Skill("打狗棒法"))
m01.add_skill(Skill("御女心经"))
m01.add_skill(Skill("降龙十巴掌"))
m01.add_skill(Skill("九阴白骨爪"))

for m0 in m01:
    print(m0.name)

把上面的继续优化,深入之后开始浅出:

"""
    类:技能类,作用暂时不写
"""

class Skill:
    def __init__(self,name):
        self.name = name
"""
    类:技能管理类
    作用:管理技能,包括对类的增加、访问
"""

class SkillManage:
    def __init__(self):
        self._skills = []
        self._index =0
    def add_skill(self,skill):
        self._skills.append(skill)
    def __iter__(self):
        # while self._index < len(self._skills):
        #     # yield 作用: 将下列代码改为迭代器模式的代码.
        #     # 生成迭代器代码的大致规则:
        #     # 1. 将yield以前的语句定义在next方法中
        #     # 2. 将yield后面的数据作为next方法返回值
        #     yield self._skills[self._index]
        #     self._index += 1
        for skill in self._skills:
            yield  skill
m01 = SkillManage()
m01.add_skill(Skill("打狗棒法"))
m01.add_skill(Skill("御女心经"))
m01.add_skill(Skill("降龙十巴掌"))
m01.add_skill(Skill("九阴白骨爪"))

for m0 in m01:
    print(m0.name)

借助yield,iter()方法仅仅两句达成我们的目标,可以被for。这就变成了生成器,每次返回一个集合中的值,但是占用的内存只有一个对象的大小。
另外可以自己写一个自己的Rang()方法,代替Rang,体会生成器的作用:

def MyRang(stopvalue):
    num = 0
    while num < stopvalue:
        yield num
        num += 1


for i in MyRang(10):
    print(i)

那么就可以自定义自己的Myrang方法,做成奇数生成器、偶数生成器等等。如下:

"""
    奇数生成器
"""
def MyOddtermRang(stopvalue):
    num = 1
    while num < stopvalue:
        yield num
        num += 2
"""
    偶数生成器
"""
def MyEventermmRang(stopvalue):
    num = 2
    while num < stopvalue:
        yield num
        num += 2


for i in MyOddtermRang(10):
    print(i)

for i in MyEventermmRang(10):
    print(i)

  从迭代对象、到迭代器,再到生成器,原理一定要理解清晰。
  三者关系,其实就是生成器 = 迭代对象 + 迭代器
比较详细的一些Python自带类型的关于迭代的举例,可参阅:https://www.cnblogs.com/notfind/p/11520124.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值