Python基础之迭代器、生成器

一、迭代器:

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

  2、可迭代对象(iterable):

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

    2)语法:  

      

    3)原理:

      

  3、迭代器对象(iterator):

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

    2)语法:

    

    3)说明及作用:

      

二、生成器(generator):

  

三、生成器函数:

  

四、基础代码:

  代码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)

五、练习实例:

  练习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)

  

猜你喜欢

转载自www.cnblogs.com/yuxiangyang/p/10752076.html