一、迭代器:
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__()whileTrue:try:#如果获取了全部元素,则执行except
#2. 获取下一个元素(迭代过程)
item = iterator.__next__()print(item)#3.停止迭代(StopIteration 错误)
exceptStopIteration:break #跳出循环体
代码2:
"""迭代器"""
classSkill:pass
classSkillIterator:"""技能迭代器"""
def __init__(self, target):
self.target=target
self.index=0def __next__(self):#如果索引越界 则抛出异常
if self.index > len(self.target) - 1:raiseStopIteration()#返回下一个元素
item =self.target[self.index]
self.index+= 1
returnitemclassSkillManager:"""可迭代对象"""
def __init__(self, skills):
self.skills=skillsdef __iter__(self):#创建迭代器对象 传递 需要迭代的数据
returnSkillIterator(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"""
classSkill: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
classSkillManager: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 inself.skills:yielditem#---------------以下是客户端代码---------------------
manager=SkillManager([Skill(), Skill(), Skill()])#for item in manager:#print(item)
iterator= manager.__iter__()whileTrue:try:
item= iterator.__next__()print(item)exceptException 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)
#生成器函数
defmy_range(stop):
start=0while start
start+= 1
#for item in my_range(5):#print(item)
iter01= my_range(5)for item initer01:print(item)
代码5:
"""内置生成器:enumerate"""list01= ["a", "b", "c"]for item inenumerate(list01):#(索引,元素)
print(item)for index, element inenumerate(list01):print(index, element)#练习:参照上述代码,自定义函数,my_enumerate.#10:46
defmy_enumerate(target):
index=0for item intarget:yield(index,item)
index+= 1
for item inmy_enumerate(list01):print(item)for index, element inmy_enumerate(list01):print(index, element)
代码6:
"""内置生成器:zip"""list02= [101,102,103]
list03= ["张三丰","张无忌","赵敏"]for item inzip(list02,list03):#(101, '张三丰')
print(item)#练习:参照上述代码,自定义函数,my_zip 11:05
defmy_zip(list01,list02):for index inrange(len(list01)):#yield (list01[index],list02[index])
yieldlist01[index], list02[index]for item inmy_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 inlist01]print(result)#def fun01(target):#for item in target:#yield item ** 2#生成表达式#for item in fun01(list01):#print(item)
result= (item ** 2 for item inlist01)for item inresult:print(item)
五、练习实例:
练习1:
#练习1:("悟空","八戒","沙僧","唐僧")#使用while + 迭代器 获取元组所有元素
t01 = ("悟空", "八戒", "沙僧", "唐僧")
iterator= t01.__iter__()whileTrue:try:
item= iterator.__next__()print(item)except:break
#练习2:{"张三丰":101,"张无忌":102,"赵敏":102}#不使用for循环,获取字典所有元素.
d01= {"张三丰": 101, "张无忌": 102, "赵敏": 102}
iterator= d01.__iter__()whileTrue:try:
key= iterator.__next__()print(key, d01[key])except:break
练习2:
"""练习:迭代员工管理器对象"""
classEmployee:pass
classEmployeeIterator:"""迭代器"""
def __init__(self, target):
self.target=target
self.index=0def __next__(self):if self.index > len(self.target) - 1:raiseStopIteration()
item=self.target[self.index]
self.index+= 1
returnitem#可迭代对象
classEmployeeManager:def __init__(self, employees):
self.all_employee=employeesdef __iter__(self):#返回迭代器
returnEmployeeIterator(self.all_employee)
manager=EmployeeManager([Employee(), Employee()])#需求:for循环自定义类的对象#for item in manager:#print(item) #
iterator= manager.__iter__()whileTrue:try:
item= iterator.__next__()print(item)except:break
练习3:
"""参照下列代码,定义MyRange类,实现相同效果."""
#15:40
classMyRangeIterator:def __init__(self, stop):
self.stop=stop
self.start=0def __next__(self):if self.start + 1 >self.stop:raiseStopIteration()
temp=self.start
self.start+= 1
returntempclassMyRange:def __init__(self, stop):
self.stop=stopdef __iter__(self):#创建迭代器对象
returnMyRangeIterator(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 initerator:print(item) #
#iterator = iterator.__iter__()#while True:#try:#item = iterator.__next__()#print(item)#except:#break
练习4:
"""改造为yield实现"""
classEmployee: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
#可迭代对象
classEmployeeManager:def __init__(self, employees):
self.all_employee=employees#def __iter__(self):
## 返回迭代器
#return EmployeeIterator(self.all_employee)
def __iter__(self):for item inself.all_employee:yielditem
manager=EmployeeManager([Employee(), Employee()])#需求:for循环自定义类的对象#for item in manager:#print(item) #
iterator= manager.__iter__()whileTrue: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
classMyRange:def __init__(self, stop):
self.stop=stop#def __iter__(self):
## 创建迭代器对象
#return MyRangeIterator(self.stop)
def __iter__(self):
start=0while start
start+= 1iterator= MyRange(5)#for item in iterator:#print(item) #
iterator= iterator.__iter__()whileTrue:try:
item= iterator.__next__()print(item)except:break
练习6:
"""生成器函数练习
体会:方法/函数,需要向外返回多个结果时,使用生成器函数.
惰性操作/延迟操作 (生成器函数的"循环(next)一次,计算一次,返回一次")"""list01= [23,3,4,556,677,68,8,98,98]#练习1:在list01中,挑出所有偶数.#要求:1)使用生成器函数实现
defget_even01(target):for item intarget:if item % 2 ==0:yielditem
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:定义函数,选出所有女同学.
classStudent:def __init__(self,name,sex,age,score):
self.name=name
self.sex=sex
self.age=age
self.score=scoredef __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),
]deffind_woman(target):for item intarget:if item.sex == "女":yielditemfor item infind_woman(list_stu):print(item)#练习3:选出所有成绩大于90的学生
deffind_by_score(target):for item intarget:if item.score > 90:yielditemfor item infind_by_score(list_stu):print(item)
练习7:
#1.创建技能类(编号,技能名称,冷却时间,攻击力,消耗法力)#创建技能列表.#-- 定义函数:查找编号是101的技能对象#-- 定义函数:查找冷却时间为0的所有技能对象#-- 定义函数:查找攻击力大于5的所有技能对象#-- 定义函数:查找攻击力大于10,并且不需要消耗法力的所有技能.
classSkillData: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返回数据,在调用者看来,更加方便吧.
deffind_demo01(target):for item intarget:if item.id == 101:returnitem
s01=find_demo01(list_skills)print(s01.id)deffind_demo02(target):for item intarget:if item.cd ==0:yielditem
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)
deffind_demo03(target):for item intarget:if item.atk > 5:yielditem#调用生成器函数,创建迭代器对象
result =find_demo03(list_skills)for item in result:#__next__()
print(item.name)print("---------------")#如果没有下一行代码,再次for使用过的生成器对象,不会再有结果.#result = find_demo03(list_skills)
for item inresult:print(item.name)#for item in find_demo03(list_skills):
#....
deffind_demo04(target):for item intarget:if item.atk > 10 and item.costSP ==0:yielditemfor item infind_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,并且不需要消耗法力的所有技能.#使用列表推导式,与生成器表达式完成#通过断点调试,审查程序执行过程,体会两项技术的差异.
classSkillData:def __init__(self, id, name, cd, atk, costSP):
self.id=id
self.name=name
self.cd=cd
self.atk=atk
self.costSP=costSPdef __str__(self):returnself.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 inresult01:print(item)for item inresult02: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 inresult01:print(item)for item inresult02: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 inresult01:print(item)for item inresult02:print(item)