迭代器 生成器
一 , 迭代器
迭代器优点
1,节省内存
2,惰性机制
3,单向,不可逆
如果对象中有__iter__函数. 那么我们认为这个对象遵守了可迭代协议.
就可以进行迭代. 这里的__iter__是帮助我们获取到对象的迭代器. 我们使用__next__()来获取
到一个迭代器中的元素.
__iter__() 获取迭代器
__next__() 获取最前面这个元素
s="山上有座庙" ko=s.__iter__() print (ko.__next__()) print (ko.__next__()) print (ko.__next__()) print (ko.__next__()) print (ko.__next__()) #结果:山 #上 #有 #座 #庙
开始的时候是__iter__()来获取迭代器,后面每次获取元素都是通过__next__()来完成.
判断是什么类型
isinstance
lst = [1, 2, 3] from collections import Iterable # 可迭代的 from collections import Iterator print(isinstance(lst, Iterable)) #判断lst是不是可迭代对象 print(isinstance(lst, Iterator)) #判断lst是不是迭代器
二 , 生成器
生成器
生成器实质上就是迭代器
生成器例子
由于函数中存在了yield. 那么这个函数就是一个生成器函数
yield跟return的作用是一样的,区别在于yield是分段执行函数,return是直接停止执行函数
def fu(): print (1) yield 222 ret=fu() ko=ret.__next__() print (ko)
#结果:1
#222
使用__next__()执行到下一个yield. send()也有这个功能.
区别:
__next__()不能赋值
send()可以赋值, 在执行send()之前执行__next__()
send可以给上一个yield的位置传递值, 不能给最后一个yield发送值. 在第一次执行生成器代码的时候不能使用send(),所以第一次执行生成器代码的时候要用__next__
def fu(): print("到处跑") a=yield print ("先去"+str(a)) b=yield print ("再去"+str(b)) c=yield print ("然后去"+str(c)) yield "最后回家" gen=fu() gen.__next__() gen.send("学校") gen.send("街上") ret=gen.send("天安门") print (ret) #结果:到处跑 # 先去学校 # 再去街上 # 然后去天安门 # 最后回家
def fu(): print ("你想去哪") a=yield print ("想去"+str(a)) b=yield print("还想去"+str(b)) c=yield print ("和"+str(c)) yield "北京" #send不能给最后一个yield传递值,所以这里的yield得给一个值,如果没有值则显示None ,如果没有yield程序会报错 ko=fu() #获取生成器 ko.__next__() #send是给上一个yield传递值的,而这里执行的是最先开始的,上面没有yield,所以这里要用__next__ ko.send("广西") #用send给上一个yield传递值 ko.send("湖南") ret=ko.send("云南") print(ret) # send和next的区别: # 1. send和next()都是让生成器向下走一次 # 2. send可以给上一个yield的位置传递值, 不能给最后一个yield发送值. 在第一次执行生 # 成器代码的时候不能使用send()
#模拟for循环
# 模拟for循环 li=['猫和老鼠','邋遢大王','黑猫警长','变形精钢','秦时明月'] ret=li.__iter__() #先拿到一个迭代器 while True: #让迭代器循环 try: #try是Python里的关键字 name=ret.__next__() #拿出列表里的每一个元素 print(name) except StopIteration: break '''正常情况下列表里面的元素拿完之后会报这个错 StopIteration 所以我们这里要引入try和except 这样当程序报这个错的时候try就会接着,然后break,这样程序就不会报错'''