python 迭代器 生成器_Python基础之迭代器、生成器

一、迭代器:

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

2、可迭代对象(iterable):

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

2)语法:

python 迭代器 生成器_Python基础之迭代器、生成器_第1张图片

3)原理:

python 迭代器 生成器_Python基础之迭代器、生成器_第2张图片

python 迭代器 生成器_Python基础之迭代器、生成器_第3张图片

3、迭代器对象(iterator):

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

2)语法:

python 迭代器 生成器_Python基础之迭代器、生成器_第4张图片

3)说明及作用:

python 迭代器 生成器_Python基础之迭代器、生成器_第5张图片

二、生成器(generator):

python 迭代器 生成器_Python基础之迭代器、生成器_第6张图片

三、生成器函数:

python 迭代器 生成器_Python基础之迭代器、生成器_第7张图片

6、内置生成器:

python 迭代器 生成器_Python基础之迭代器、生成器_第8张图片

7、生成器表达式:

ecf3979dab9da93ce45f1aca3c21db55.png

四、基础代码:

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

你可能感兴趣的:(python,迭代器,生成器)