迭代器与生成器
1.迭代器
1.迭代器是一个可以记住遍历的位置的对象。
iterable 可迭代的对象
iterator 迭代器
iter 迭代
int类型中没有__iter__方法,因为int是不可迭代的对象
查看数据类型中的方法:dir([object])
2.迭代器的特点:
1.只能向前
2.几乎不占内存,节省内存
3.惰性机制
4.可以for循环
3.迭代器中的常用方法__iter__()创建迭代器,__next__()输出迭代器的下一个元素4.迭代器模拟for循环
li = "1234" a = li.__iter__() # 创建迭代器 print(a.__next__()) # 输出,调用一次就输入一个元素 <<<<1 print(a.__next__()) <<<<2 print(a.__next__()) <<<<3 print(a.__next__()) <<<<4 # 注意:当后面没有元素可迭代的时候会报错
4.迭代器模拟for循环
lst = ["卢本伟","刘二狗","铁蛋","神仙"] s = lst.__iter__() # 创建迭代器 while 1: # 循环,当循环到后面的时候会没有元素就会报错,所以要用异常处理 try: #尝试执行 a = s.__next__() print(a) except StopIteration: # 处理错误 break <<<< 卢本伟 刘二狗 铁蛋 神仙
5.判断是否是可迭代对象跟迭代器
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
lst = ["卢本伟","刘二狗","铁蛋","神仙"] a = lst.__iter__() print("__iter__"in dir(lst)) #判断是否是可迭代的对象,可迭代对象方法中只要__iter__,没有__next__ <<<<True print("__next__" in dir(lst)) <<<<False print("__next__" and "__iter__"in dir(a)) #判断是否是迭代器,迭代器的方法中__next__与__iter__都有 <<<<True # 迭代器的方法里面__iter__跟__next__都有
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
lst = ["卢本伟","刘二狗","铁蛋","神仙"] a = lst.__iter__() from collections.abc import Iterable # 可迭代的 引入模块 print(isinstance(lst,Iterable)) #判断是否是可迭代的 <<<<True from collections.abc import Iterator #迭代器 引入模块 print(isinstance(a,Iterator)) #判断是否是迭代器 <<<<True
2.生成器
使用了 yield 的函数被称为生成器(generator)
1.如果函数中有yield这个函数,那么这个函数就是生成器函数 ,生成器函数()获取的是生成器,这个时候不执行函数
def func(): print("娃哈哈") yield 1 # 只要函数里用了yield,再调用函数是不会执行函数的 print("666") yield 3 func() <<<<Process finished with exit code 0
2.yield 相当于return 可以返回数据,但是不会彻底中断函数,分段执行函数
def func(): print("娃哈哈") yield 1 # 只要函数里用了yield,再调用函数是不会执行函数的 print("666") yield 3 gen =func() a =gen.__next__() # 执行到第一个yield然后停止 <<<<娃哈哈 print(a) # 返回值为1 <<<<1 b =gen.__next__() #执行到下一个yield然后停止 <<<<666 print(b) # 返回值为3 <<<3
3.send()
send()跟__next__()是一样的,可以执行到下一个yield,可以给上一个yield位置传值,send()里面必须要给值不然会报错
def eat(): print("我吃什么") a = yield "馒头" print("a=",a) b = yield "鸡蛋灌饼" print("b=",b) c = yield "韭菜盒子 " print("c=",c) yield "GAME OVER" # 最后一个传不了值,因为要传值就要有下一个yield,就会进入死循环 gen = eat() # 获取迭代器 ret = gen.__next__() # 第一个不能用send,因为没有前一个yield <<<<我吃什么 print(ret) <<<<馒头 ret2 = gen.send("胡椒汤") # 传给第一个yield,a <<<<a= 胡椒汤 print(ret2) <<<<鸡蛋灌饼 ret3 = gen.send("狗粮") # 传给上一个yield,b <<<<b= 狗粮 print(ret3) <<<<韭菜盒子 ret4 = gen.send("猫粮") # 传给上一个yield,c <<<<c= 猫粮 print(ret4) <<<<GAME OVER
上面的运行顺序:
4.生成器可以使用for循环
def fuanc(): yield 1 yield 2 yield 3 yield 4 for i in fuanc(): print(i) <<<< 1 2 3 4 # 可以拿值 print(list(fuanc())) <<<<[1, 2, 3, 4]
3.推导式
1.列表推导式
语法:li=[结果 for 判断]
# 奇数列表 li = [i for i in range(1,20) if i%2==1] print(li) <<<< [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
2.字典推导式
语法:dic = { k:v for循环 条件筛选}
# key跟value对调 dic ={"jj":"林俊杰","jay":"周杰伦","zs":"赵四","ln":"刘能"} de = { v:k for k,v in dic.items() } print(de) <<<<{'林俊杰': 'jj', '周杰伦': 'jay', '赵四': 'zs', '刘能': 'ln'}
3.生成器表达式
tu = (i for i in range(1,10)) #元组没有推导式,这个是生成器表达式 a = tu.__next__() print(a) <<<<1