• Python基础之迭代器、生成器


    一、迭代器:

      1、迭代:每一次对过程的重复称为一次迭代,而每一次迭代得到的结果会作为下一次迭代的初始值。例如:循环获取容器中的元素。

      2、可迭代对象(iterable):

        1)定义:具有__iter__函数的对象,可以返回迭代器对象

        2)语法:  

          

        3)原理:

          

      

      3、迭代器对象(iterator):

        1)定义:可以被next()函数调用并返回下一个值的对象

        2)语法:

        

        3)说明及作用:

          

    二、生成器(generator):

      

    三、生成器函数:

      

       6、内置生成器:

        

      7、生成器表达式:

        

    四、基础代码:

      代码1:

      

    """
        可迭代对象:具有__iter__()方法,可以返回迭代器的对象.
    """
    list01 = [2,434,5,6,8]
    
    # for item in list01:
    #     print(item)
    
    # 面试题:
    # 能够被for循环的条件是:可迭代对象(具有__iter__()方法的对象)
    
    # for循环原理
    # 1. 获取迭代器对象
    # 2. 循环迭代(调用迭代器的__next__方法)
    # 3. 捕获StopIteration异常
    
    #1.
    # iterator = list01.__iter__()
    #2.
    # item = iterator.__next__()
    # print(item)
    #
    # item = iterator.__next__()
    # print(item)
    #
    # item = iterator.__next__()
    # print(item)
    #
    # item = iterator.__next__()
    # print(item)
    #
    # item = iterator.__next__() # 最后一次
    # print(item)
    # 3.
    # item = iterator.__next__()# StopIteration
    # print(item)
    
    # 1. 获取迭代器对象
    iterator = list01.__iter__()
    while True:
        try:# 如果获取了全部元素,则执行except
            # 2. 获取下一个元素(迭代过程)
            item = iterator.__next__()
            print(item)
            # 3.停止迭代(StopIteration 错误)
        except StopIteration:
            break # 跳出循环体

      代码2:

      

    """
        迭代器
    """
    
    
    class Skill:
        pass
    
    
    class SkillIterator:
        """
            技能迭代器
        """
        def __init__(self, target):
            self.target = target
            self.index = 0
    
        def __next__(self):
    
            # 如果索引越界 则抛出异常
            if self.index > len(self.target) - 1:
                raise StopIteration()
            # 返回下一个元素
            item = self.target[self.index]
            self.index += 1
            return item
    
    
    class SkillManager:
        """
            可迭代对象
        """
        def __init__(self, skills):
            self.skills = skills
    
        def __iter__(self):
            # 创建迭代器对象  传递 需要迭代的数据
            return SkillIterator(self.skills)
    
    
    #---------------以下是客户端代码---------------------
    
    manager = SkillManager([Skill(), Skill(), Skill()])
    # for item in manager.skills:
    for item in manager:# 获取manager对象中列表元素(获取manager对象的聚合类型对象元素)
        print(item)
    # iterator = manager.__iter__()
    # while True:
    #     try:
    #         item = iterator.__next__()
    #         print(item)
    #     except:
    #         break

      代码3:

      

    """
        迭代器 --> yield
    
    """
    
    class Skill:
        pass
    
    
    # class SkillIterator:
    #     """
    #         技能迭代器
    #     """
    #     def __init__(self, target):
    #         self.target = target
    #         self.index = 0
    #
    #     def __next__(self):
    #         if self.index > len(self.target) - 1:
    #             raise StopIteration()
    #         item = self.target[self.index]
    #         self.index += 1
    #         return item
    
    
    class SkillManager:
        def __init__(self, skills):
            self.skills = skills
    
        # def __iter__(self):
        #     return SkillIterator(self.skills)
    
        def __iter__(self):
            """
                执行过程:
                1.调用__iter__()方法不执行
                2.调用__next__()方法时执行,到yield语句暂时离开.
                3.再次调用__next__()方法时,从上次离开的代码开始执行,到yield语句暂时离开
                4. 待执行完方法体,抛出StopIteration异常.
    
                原理:如果方法体中包含yield关键字,那么会自动生成迭代器对象.
                生成迭代器代码的大致规则: 
                1. 将yield关键字以前的代码,放到__next__方法中.
                2. 将yield关键字以后的数据,作为__next__方法的返回值
            """
            # print("准备返回第一个元素")
            # yield self.skills[0]  # 暂时离开点   再次执行点
            #
            # print("准备返回第二个元素")
            # yield self.skills[1]
            #
            # print("准备返回第三个元素")
            # yield self.skills[2]
    
            for item in self.skills:
                yield item
    
    
    
    #---------------以下是客户端代码---------------------
    
    manager = SkillManager([Skill(), Skill(), Skill()])
    
    # for item in manager:
    #     print(item)
    
    iterator = manager.__iter__()
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except Exception as e:
            print(e)
            break

      代码4:

      

    """
        yield -->  生成器函数
    """
    
    # class MyRange:
    #     def __init__(self, stop):
    #         self.stop = stop
    #
    #     def __iter__(self):
    #         start = 0
    #         while start < self.stop:
    #             yield start
    #             start += 1
    #
    # for item in MyRange(5):
    #     print(item)
    
    
    # 生成器函数
    def my_range(stop):
        start = 0
        while start < stop:
            yield start
            start += 1
    
    # for item in my_range(5):
    #     print(item)
    
    iter01 = my_range(5)
    for item in iter01:
         print(item)

      代码5:

      

    """
        内置生成器:enumerate
    """
    
    list01 = ["a", "b", "c"]
    
    for item in enumerate(list01):
        # (索引,元素)
        print(item)
    
    for index, element in enumerate(list01):
        print(index, element)
    
    # 练习:参照上述代码,自定义函数,my_enumerate.
    # 10:46
    
    def my_enumerate(target):
        index = 0
        for item in target:
            yield (index,item)
            index += 1
    
    for item in my_enumerate(list01):
        print(item)
    
    for index, element in my_enumerate(list01):
        print(index, element)

      代码6:

      

    """
        内置生成器:zip
    """
    
    list02 = [101,102,103]
    list03 = ["张三丰","张无忌","赵敏"]
    for item in zip(list02,list03):
        # (101, '张三丰')
        print(item)
    
    #练习:参照上述代码,自定义函数,my_zip  11:05
    def my_zip(list01,list02):
        for index in range(len(list01)):
            # yield (list01[index],list02[index])
            yield list01[index], list02[index]
    
    for item in my_zip(list02,list03):
        # (101, '张三丰')
        print(item)

      代码7:

      

    """
        生成器表达式
    """
    
    list01 = [2,3,4,6]
    # result = []
    # for item in list01:
    #     result.append(item ** 2)
    
    # 列表推导式[]     字典推导式 {键:值 for ...}   集合 { for ... }
    result = [item ** 2 for item in list01]
    print(result)
    
    # def fun01(target):
    #     for item in target:
    #         yield item ** 2
    # 生成表达式
    # for item in fun01(list01):
    #     print(item)
    
    result = (item ** 2 for item in list01)
    for item in result:
        print(item)

    五、练习实例:

      练习1:

      

    # 练习1:("悟空","八戒","沙僧","唐僧")
    # 使用while + 迭代器 获取元组所有元素
    t01 = ("悟空", "八戒", "沙僧", "唐僧")
    iterator = t01.__iter__()
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except:
            break
    
    # 练习2:{"张三丰":101,"张无忌":102,"赵敏":102}
    # 不使用for循环,获取字典所有元素.
    
    d01 = {"张三丰": 101, "张无忌": 102, "赵敏": 102}
    iterator = d01.__iter__()
    while True:
        try:
            key = iterator.__next__()
            print(key, d01[key])
        except:
            break

      练习2:

      

    """
        练习:迭代员工管理器对象
        
    """
    
    
    class Employee:
        pass
    
    
    class EmployeeIterator:
        """
            迭代器
        """
        def __init__(self, target):
            self.target = target
            self.index = 0
    
        def __next__(self):
            if self.index > len(self.target) - 1:
                raise StopIteration()
            item = self.target[self.index]
            self.index += 1
            return item
    
    
    # 可迭代对象
    class EmployeeManager:
        def __init__(self, employees):
            self.all_employee = employees
    
        def __iter__(self):
            # 返回迭代器
            return EmployeeIterator(self.all_employee)
    
    
    manager = EmployeeManager([Employee(), Employee()])
    
    # 需求:for循环自定义类的对象
    # for item in manager:
    #     print(item)  #
    
    iterator = manager.__iter__()
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except:
            break

      练习3:

        

    """
        参照下列代码,定义MyRange类,实现相同效果.
        
    """
    
    # 15:40
    class MyRangeIterator:
        def __init__(self, stop):
            self.stop = stop
            self.start = 0
    
        def __next__(self):
            if self.start + 1 > self.stop:
                raise StopIteration()
            temp = self.start
            self.start += 1
            return temp
    
    
    class MyRange:
        def __init__(self, stop):
            self.stop = stop
    
        def __iter__(self):
            # 创建迭代器对象
            return MyRangeIterator(self.stop)
    
    
    # for item in range(5):
    #     print(item)#
    
    # for item in MyRange(5):
    #     print(item)#0 1 2 3 4
    
    iterator = MyRange(5)
    for item in iterator:
        print(item)  #
    
    # iterator = iterator.__iter__()
    # while True:
    #     try:
    #         item = iterator.__next__()
    #         print(item)
    #     except:
    #         break

      练习4:

        

    """
         改造为yield实现
    """
    
    
    class Employee:
        pass
    
    
    # class EmployeeIterator:
    #     """
    #         迭代器
    #     """
    #     def __init__(self, target):
    #         self.target = target
    #         self.index = 0
    #
    #     def __next__(self):
    #         if self.index > len(self.target) - 1:
    #             raise StopIteration()
    #         item = self.target[self.index]
    #         self.index += 1
    #         return item
    
    
    # 可迭代对象
    class EmployeeManager:
        def __init__(self, employees):
            self.all_employee = employees
    
        # def __iter__(self):
        #     # 返回迭代器
        #     return EmployeeIterator(self.all_employee)
    
        def __iter__(self):
            for item in self.all_employee:
                yield item
    
    
    manager = EmployeeManager([Employee(), Employee()])
    
    # 需求:for循环自定义类的对象
    # for item in manager:
    #     print(item)  #
    
    iterator = manager.__iter__()
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except:
            break

      练习5:

      

    """
         改造为yield实现
    """
    
    
    # class MyRangeIterator:
    #     def __init__(self, stop):
    #         self.stop = stop
    #         self.start = 0
    #
    #     def __next__(self):
    #         if self.start + 1 > self.stop:
    #             raise StopIteration()
    #         temp = self.start
    #         self.start += 1
    #         return temp
    
    
    class MyRange:
        def __init__(self, stop):
            self.stop = stop
    
        # def __iter__(self):
        #     # 创建迭代器对象
        #     return MyRangeIterator(self.stop)
    
        def __iter__(self):
            start = 0
            while start < self.stop:
                yield start
                start += 1
    
    
    iterator = MyRange(5)
    # for item in iterator:
    #     print(item)  #
    
    iterator = iterator.__iter__()
    while True:
        try:
            item = iterator.__next__()
            print(item)
        except:
            break

      练习6:

      

    """
        生成器函数练习
        体会:方法/函数,需要向外返回多个结果时,使用生成器函数.
             惰性操作/延迟操作 (生成器函数的"循环(next)一次,计算一次,返回一次")
    
    """
    list01 = [23,3,4,556,677,68,8,98,98]
    # 练习1:在list01中,挑出所有偶数.
    # 要求:1)使用生成器函数实现
    def get_even01(target):
        for item in target:
            if item % 2 == 0:
                yield item
    
    iter01 = get_even01(list01)# 没有执行方法体
    for item in iter01:# 循环(next)一次,计算一次,返回一次
        print(item)
    
    # def get_even02(target):
    #     result = []
    #     for item in target:
    #         if item % 2 == 0:
    #             result.append(item)
    #     return result
    #
    # iter01 = get_even02(list01)# 执行方法体,将所有结果存在内存中.
    # for item in iter01:
    #     print(item)
    
    # 练习2:定义函数,选出所有女同学.
    class Student:
        def __init__(self,name,sex,age,score):
            self.name = name
            self.sex = sex
            self.age = age
            self.score = score
    
        def __str__(self):
            return "%s--%s--%d--%d"%(self.name,self.sex,self.age,self.score)
    
    list_stu = [
        Student("张无忌","",28,82),
        Student("赵敏","",25,95),
        Student("周芷若","",26,88),
    ]
    
    def find_woman(target):
        for item in target:
            if item.sex == "":
                yield item
    
    for item in find_woman(list_stu):
        print(item)
    
    # 练习3:选出所有成绩大于90的学生
    def find_by_score(target):
        for item in target:
            if item.score > 90:
                yield item
    
    for item in find_by_score(list_stu):
        print(item)

      练习7:

      

    # 1.创建技能类(编号,技能名称,冷却时间,攻击力,消耗法力)
    #   创建技能列表.
    #   -- 定义函数:查找编号是101的技能对象
    #   -- 定义函数:查找冷却时间为0的所有技能对象
    #   -- 定义函数:查找攻击力大于5的所有技能对象
    #   -- 定义函数:查找攻击力大于10,并且不需要消耗法力的所有技能.
    
    class SkillData:
        def __init__(self, id, name, cd, atk, costSP):
            self.id = id
            self.name = name
            self.cd = cd
            self.atk = atk
            self.costSP = costSP
    
    
    list_skills = [
        SkillData(101, "降龙十八掌", 60, 10, 5),
        SkillData(102, "如来神掌", 50, 15, 0),
        SkillData(103, "六脉神剑", 0, 20, 8),
        SkillData(104, "一阳指", 0, 50, 15),
        SkillData(105, "冷酷追击", 15, 30, 9),
    ]
    
    
    # 因为需要查找的结果只有一个,所以使用return返回数据.
    # 比使用yield返回数据,在调用者看来,更加方便吧.
    def find_demo01(target):
        for item in target:
            if item.id == 101:
                return item
    
    s01 = find_demo01(list_skills)
    print(s01.id)
    
    
    def find_demo02(target):
        for item in target:
            if item.cd == 0:
                yield item
    
    result = find_demo02(list_skills)
    # 不能获取指定结果
    # 因为:此时生成器函数并没有计算处结果.
    # print(result[1].name)
    # for item in result:
    #     print(item.name)
    
    
    result = find_demo02(list_skills)
    # 通过生成器创建列表
    # 由惰性查找(优势:节省内存) 转换为 立即查找(优势:灵活获取结果)
    result = list(result)
    # print(result[1].name)
    
    
    def find_demo03(target):
        for item in target:
            if item.atk > 5:
                yield item
    
    # 调用生成器函数,创建迭代器对象
    result = find_demo03(list_skills)
    for item in result:# __next__()
        print(item.name)
    
    print("---------------")
    # 如果没有下一行代码,再次for使用过的生成器对象,不会再有结果.
    # result = find_demo03(list_skills)
    for item in result:
        print(item.name)
    
    # for item in find_demo03(list_skills):
        # ....
    
    
    def find_demo04(target):
        for item in target:
            if item.atk > 10 and item.costSP == 0:
                yield item
    
    for item in find_demo04(list_skills):
        print(item.name)

      练习8:

      

    list02 = [2,3,4,6]
    # 练习:使用列表推导式,与生成器表达式,获取list02中,大于3的数据.
    
    result01 = [item for item in list02 if item > 3 ] # 本行代码:执行所有操作,保存所有结果
    result02 = (item for item in list02 if item > 3 ) # 本行代码:返回生成器对象
    
    for item in result01:# 从结果中获取数据
        print(item)
    
    for item in result02:# 循环一次,计算一次,返回一次
        print(item)

      练习9:

      

    # 1.创建技能类(编号,技能名称,冷却时间,攻击力,消耗法力)
    #   创建技能列表. 
    #   -- 定义函数:查找冷却时间为0的所有技能对象
    #   -- 定义函数:查找攻击力大于5的所有技能对象
    #   -- 定义函数:查找攻击力大于10,并且不需要消耗法力的所有技能.
    #   使用列表推导式,与生成器表达式完成
    #   通过断点调试,审查程序执行过程,体会两项技术的差异.
    
    
    class SkillData:
        def __init__(self, id, name, cd, atk, costSP):
            self.id = id
            self.name = name
            self.cd = cd
            self.atk = atk
            self.costSP = costSP
    
        def __str__(self):
            return self.name
    
    list_skills = [
        SkillData(101, "降龙十八掌", 60, 10, 5),
        SkillData(102, "如来神掌", 50, 15, 0),
        SkillData(103, "六脉神剑", 0, 20, 8),
        SkillData(104, "一阳指", 0, 50, 15),
        SkillData(105, "冷酷追击", 15, 30, 9),
    ]
    
    
    # def find_demo02(target):
    #     for item in target:
    #         if item.cd == 0:
    #             yield item
    
    result01 = (item for item in list_skills if item.cd == 0)
    result02 = [item for item in list_skills if item.cd == 0]
    
    for item in result01:
        print(item)
    
    for item in result02:
        print(item)
    
    # def find_demo03(target):
    #     for item in target:
    #         if item.atk > 5:
    #             yield item
    
    result01 = (item for item in list_skills if item.atk > 5)
    result02 = [item for item in list_skills if item.atk > 5]
    
    for item in result01:
        print(item)
    
    for item in result02:
        print(item)
    
    # def find_demo04(target):
    #     for item in target:
    #         if item.atk > 10 and item.costSP == 0:
    #             yield item
    result01 = (item for item in list_skills if item.atk > 10 and item.costSP == 0)
    result02 = [item for item in list_skills if item.atk > 10 and item.costSP == 0]
    
    for item in result01:
        print(item)
    
    for item in result02:
        print(item)

      

  • 相关阅读:
    把影响集中到一个点
    How to avoid Over-fitting using Regularization?
    适定性问题
    Numerical Differentiation 数值微分
    What Every Computer Scientist Should Know About Floating-Point Arithmetic
    Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
    What is the difference between iterations and epochs in Convolution neural networks?
    Every norm is a convex function
    Moore-Penrose Matrix Inverse 摩尔-彭若斯广义逆 埃尔米特矩阵 Hermitian matrix
    perl 类里的函数调用其他类的函数
  • 原文地址:https://www.cnblogs.com/yuxiangyang/p/10752076.html
Copyright © 2020-2023  润新知