迭代器使用
在迭代器使用之前,先举个例子:
list01 = [1,2133,345,5,6]
# for item in list01:
# print(item)
# for 循环原理:
# 1. 获取迭代器对象
# 2. 循环获取下一个元素
# 3. 遇到StopIteration停止迭代
# 可以被for的条件(什么是可迭代对象):
# 可以获取迭代器对象(具有__iter__方法)
#1. 获取迭代器对象
iterator = list01.__iter__()
#2. 获取下一个元素
item = iterator.__next__()
print(item)
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
print(iterator.__next__())
#3. 直到错误 StopIteration 停止
print(iterator.__next__())
iterator = list01.__iter__()
while True:
try:
print(iterator.__next__())
except StopIteration:
break # 跳出循环
练习题1:(“悟空”,“八戒”,“唐僧”,“沙僧”,“女儿国国王”)
使用while + 迭代器 获取元组所有元素
tuple = ('悟空','八戒','唐僧','沙僧','女儿国国王')
tuple1 = tuple.__iter__()
while True:
try:
print(tuple1.__next__())
except StopIteration:
break
结果:
悟空
八戒
唐僧
沙僧
女儿国国王
练习2:{“悟空”:2000,“八戒”:3000,“唐僧”:1000,“沙僧”:2800}
不使用for,获取字典所有元素
dict1 = {'悟空':2000, '八戒':3000, '唐僧':1000, '沙僧':2800, }
dict01 = dict1.__iter__()
while True:
try:
key = dict01.__next__()
value = dict1[key]
print(key,value)
except StopIteration:
break
结果:
唐僧 1000
沙僧 2800
八戒 3000
悟空 2000
以上的两个代码都是将元组、字典里的元素逐个打印出来。这种我们认为是迭代的使用。
可迭代对象iterable:
每一次对过程的重复称为‘迭代一次’,每一次重复的结果作为下一次迭代的初始值。
可迭代对象iterable:
-
定义:具有__iter__函数的对象。可以返回迭代器对象。
-
语法:
---创建的过程 class 可迭代对象类名: def__iter__(self) ---使用 for 变量名 in 可迭代对象: 语句
-
原理:
变量 = 可迭代对象.__iter__() while True: try: 元素 = 变量.__next__() except: break
迭代器iterator:
按照惯例,还是还有个参考代码:
4. 参考代码:
```
“”"
迭代器
“”"
class Skill:
pass
class SkillIterator:
"""
技能迭代器
"""
def __init__(self, target):
self.target = target
self.index = 0
# def __next__(self):
# item = self.target[self.index]
# self.index += 1
# return item
def __next__(self):
# 如果索引越界 则停止迭代
if self.index >= len(self.target):
raise StopIteration()
item = self.target[self.index]
self.index += 1
return item
class SkillManager:
def __init__(self, skills):
self.skills = skills
def __iter__(self):
# 1. 创建迭代器对象
# 2. 传递需要迭代的数据
return SkillIterator(self.skills)
manager = SkillManager([Skill(), Skill(), Skill()])
# for item in manager:
# print(item)
iterator = manager.__iter__()
# 使用迭代器获取manager中的技能列表
while True:
try:
item = iterator.__next__()
print(item)
except:
break
```
-
定义:具有__next__的对象,可以获取下一个元素。
-
语法:
class 迭代器名称: def __init__(self,参数): self.数据 = 参数 #数据就是聚合对象 def __next__(): if 没有元素: raise Stoplteration #停止迭代 return 数据中的元素#聚合对象的元素
-
作用:使用者只需要通过一种方式
__next__
,便可简单明了的获取聚合对象中的元素 -
练习题:
参照下列代码。自定义MyRange类。实现以下效果 参照代码: for item in range(5) print(item) #0 1 2 3 4 实现代码: for item in MyRange(5): print(item) #0 1 2 3 4
习题答案: class MyRangeIterator: #迭代器 def __init__(self, stop): self.stop = stop self.start = 0 def __next__(self): #创建可迭代对象 if self.start >= 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 MyRange(5): print(item) # 0 1 2 3 4
迭代———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):
# raise StopIteration()
# item = self.target[self.index]
# self.index += 1
# return item
class SkillManager:
def __init__(self, skills):
self.skills = skills
def __iter__(self):# 15:30 上课
# SkillIterator(self.skills)
# 本质:
# 解释器检测到yield关键字,就会生成迭代器对象。
# 自动生成迭代器的大致规则:
# 1. yield 关键字以前的代码会放到__next__方法中
# 2. yield 关键字后面的数据会作为__next__方法的返回值
# 现象:
# 调用当前方法时,不执行。
# 当调用__next__方法时,才执行。
# 执行到 yield 关键字,暂时离开。
# 当再次调用__next__方法时,继续执行。
# 执行到 yield 关键字,暂时离开。
# .....
# print("我的第一次")
# yield self.skills[0]
#
# print("我的第二次")
# yield self.skills[1]
#
# print("我的第三次")
# yield self.skills[2]
for i in range(len(self.skills)):
yield self.skills[i]
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(type(e))
break
生成器generator:
-
生成器的本质:
"""生成器本质 class MyRangeIterator: def __init__(self, stop): self.stop = stop self.start = 0 def __next__(self): if self.start >= self.stop: raise StopIteration() temp = self.start self.start += 1 return temp class MyGenerator: def __init__(self, stop): self.stop = stop def __iter__(self): return MyRangeIterator(self.stop) for item in MyGenerator(5): print(item) g01 = MyGenerator(5) iter01 = g01.__iter__() while True: try: print(iter01.__next__()) except: break """
-
练习题:将MyRange修改为yield
def my_range(stop): start = 0 while start < stop: yield start start += 1 for item in my_range(5): print(item) # 0 1 2 3 4
-
定义:能够动态(循环一次,计算一次返回一次)提供数据的可迭代对象
-
作用:在循环过程中,按照某种算法推算数据,不必创建容器存储完整的结果,而节省内存空间,数据量越大,优势越明显
-
惰性操作:在需要的时候才计算结果,
生成器函数:
-
定义:含有yield关键字的函数,返回值是生成器对象,
-
语法:
--创建: def 方法名(): ... yield 数据 --使用 for 变量名 in 方法名(): 语句
-
本质:
--创建 class 生成器名称: def __iter__(self): return 迭代器对象 --使用 生成器变量名 = 生成器名称() 迭代器变量名 = 变量名.__iter__() while True: try: print(迭代器变量名.__next__()) except: break
-
语法说明:
--调用生成器函数会返回迭代器对象,不执行函数体。 --执行过程: 1.调用生成器函数,自动创建迭代器对象, 2.调用迭代器对象的__next__()方法才执行生成器函数体 3.每次执行到yield关键字是返回数据,暂时离开。 4.带下次调用__next__()方法继续执行。
-
生成迭代器对象原理:
1.将yield关键字以前的代码放到__next__()方法中。 2.将yield关键字以后的数据作为__next___()方法返回值。
生成器表达式
按照惯例,先熟悉代码。
list01 = [2,3,4,5]
# list02 = []
# for item in list01:
# list02.append(item ** 2)
# 列表推导式
list02 = [item ** 2 for item in list01] # 执行过后,内存中就存储了所有数据
for item in list02:
print(item)
# 生成器表达式
g03 = (item ** 2 for item in list01) # 执行过后,没有计算结果。
print(g03)
for item in g03: # 循环一次 计算一次 返回一次
print(item)
- 语法:(表达式 for 变量 in 可迭代对象 [if 条件])
- 定义:用推导式语法创建的生成器对象。
zip-----将多个可迭代对象的元素组合成一个个元组:
-
zip:将多个可迭代对象的元素组合成一个个元组
-
练习:
""" # 练习:my_zip list02 = ["A", "B", "C"] for item in zip(list01, list02): print(item) """ def my_zip(target01,target02):# *args for i in range(len(target01)): yield (target01[i],target02[i]) list01 = ["a", "b", "c"] list02 = ["A", "B", "C"] for item in my_zip(list01, list02): print(item)
-
练习2:
list01 = ["a", "b", "c"] # enumerate : 将列表中的每个元素 与 索引 组合为一个元组 16:28 # for item in enumerate(list01): # print(item[0],item[1]) def my_enumerate(list_target): index = 0 for item in list_target: yield (index, item) index += 1 for item in my_enumerate(list01): print(item[0], item[1]) for index, item in my_enumerate(list01): print(index, item) #练习:my_zip #zip:将多个可迭代对象的元素组合成一个个元组。 list02 = ["A", "B", "C"] for item in zip(list01, list02): print(item)