迭代器和生成器
迭代器的介绍:
作用:对于大数据量的访问,可以节省内存空间
原理:迭代器不会一次性得到所有的数据,而是循环一次计算/读取一次,相当于只使用了一份内存
应用:for循环本质上就是将可迭代对象转换为迭代器,逐一访问
概念:_iter_如果这个对象含有_iter_方法,我们就说它是可迭代对象
内置函数dir()可以获取当前数据对象内置方法和属性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwtdDcZU-1650251181839)(C:/Users/%E5%88%98%E9%91%AB/AppData/Roaming/Typora/typora-user-images/image-20220406001841830.png)]
t1 = [1,2,3,"a","b","b"] print(dir(t1))
观察对象中是否有 _iter_方法的,可以使用下面的语句直接得出结论
print('__iter__' in dir(data)) #如果是可迭代对象输出True
python中的可迭代对象有:列表、元组、字典、集合、字符串墩号文件
可迭代对象,可以遍历数据
f=open("a.txt","r")
print("__iter__in" in dir(f))
#文件内存储abcd,每个字母一行
for i in f:
print(i,end="") #输出abcd
概念:如果同时含有_iter_和_next_这两个方法,那就说它是迭代器。
所以:
- 可迭代的对象不一定是迭代器
- 迭代器一定是可迭代对象
- 主要作用:可以通过next()控制元素访问的过程
for 循环在遍历的时候:
- 第一件事情是调用__iter__()获得一个迭代器
- 第二件事是循环调用__next__()魔术方法
# 模拟实现
t1=[1,2,3,4,5,6]
#转化为一个迭代器
#it1=iter(t1)
#methods=dir(it)
#print("__iter__" in methods and "__next__" in methods)
#使用next()方法可以遍历迭代器
t1=[1,2,3,"a","b","c"]
it=iter(t1)
res=next(it)
print(res)
#每一次调用next(),指针往下移动一格
res=next(it) #访问到最后一个元素时,继续访问会报错
print(res) #错误类型:StopIteration
每一次调用next(),迭代器的指针往下移动一
print("遍历开始")
while True:
try:
print(next(it)) #访问完最后一个元素时,继续访问会报错
#错误类型:StopIteration
#捕获StopIteration异常
except StopIteration:
print("遍历结束")
break
迭代器重置
#迭代器的遍历是单向的,不能够倒回
#可以通过重置迭代器的方法实现从头访问
t1=[1,2,3,4,5,6]
#转化为一个迭代器
it1=iter(t1)
for i in range(len(t1)):
print(next(it1))
#如果需要重新访问一遍,就需要重置迭代器
it1=iter(it)
for i in range(len(t1)):
print(next(it1))
#这样的方式也可以进行迭代
print(it.__next__())
定义一个反转字符串的迭代器
class Reverse:
def __init__(self,data):
self.data=data
self.index=len(data)
def __iter__(self):
self.index=len(self.data)
return self
def __next__(self):
if self.index==0:
#抛出异常和c/cpp里面的assert作用相似
raise StopIteraton
self.index=self.index-1
return self.data[self.index]
#获取迭代器对象
res=Reverse("abcd")
for char in res:
print(char,end="")
print("*"*30)
for char in res:
print(char,end="")
#Iterator 表示迭代器类型
#Iterable 表示可迭代对象
t1=[1,2,3,"a","b","c"]
res=isinstance(t1,Iterable)
print(res)
res=isinstance(iter(t1),Iterator)
#随机数生成器
import random
def getnum(length):
for i in range(length):
#yield翻译成生成的意思
yield f"当前生成的随机数为:{random.randint(1,10)}"
def getresult(x):
print("接收到的x:",x)
y=yield x+x
print("接收到的y:",y)
z=yield y**3
print("接收到的z:",z)
z=yield z+100
result=getresult(2)
print("第一次访问:",res.send(None))
print("第二次访问:",res.send(10))
print("第三次访问:",res.send(50))
#yield 是生成产生的意思
def getsquare(num):
x=num
while True:
x=yield x**2
gs=getsquare(1)
print(gs.send(None))
print(gs.send(10))
print(gs.send(40))
#yield from
#从可迭代对象中产生数据:逐一返回每个元素
def getresult1():
t1=[1,2,3,4]
yield t1
#得到一个迭代器
res1=getresult1()
print(next(res1))
print(res1.send(None))
def getresult2():
t2=[1,2,3,4]
yield from t2
res2=getresult2()
for i in res2:
print(i,end=" ")