迭代器和生成器
一、迭代器
之前我们一直在用可迭代对象进行迭代操作,那么到底什么是可迭代对象。str,list,tuple,dict,set这些都是可迭代对象,因为它们都遵循可迭代协议。查看对象是否可迭代可以使用dir(对象)再把其打印出来如果其中有__iter__就说明其属于可迭代对象。
for循环使用的就是迭代原则,一开始是用__iter__()来获取迭代器,后面每次获取元素都是通过__next__()完成,当程序遇到StopIteration结束循环。
什么叫做迭代器?迭代器英文意思是iterator。
l = [1,2,3,4]
l_iter = l.__iter__() # 将可迭代的转化成迭代器
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
for循环,能遍历一个可迭代对象,他的内部到底进行了什么?
- 将可迭代对象转化成迭代器。(可迭代对象.__iter__())
- 内部使用__next__方法,一个一个取值。
- 加了异常处理功能,取值到底后自动停止。
用while循环模拟for循环:
l = [1,2,3,4]
l_iter = l.__iter__()
while True:
try:
item = l_iter.__next__()
print(item)
except StopIteration:
break
二、生成器
生成器的实质就是迭代器
在python中有三种方式来获取生成器:
1.通过生成器函数
2.通过各种推导式来实现生成器
3.通过数据转换也可以获取生成器
def func():
print("111")
yield 222
ret = func()
print(ret)
此时就生成了一个生成器,由于函数中存在yield那么这个函数就是一个生成器函数。如何来执行这个函数呢,见下面:
那么我们看到,yield和return的效果是一样的有什么区别呢?yield是分段来执行一个函数,return是直接停止执行函数。
当程序运行完最后一个yield,那么后i按继续进行__next__()程序会报错。
def cloth():
for i in range(0,10000):
yield "衣服"+str(i)
cl = cloth()
print(cl.__next__())
print(cl.__next__())
print(cl.__next__())
区别:第一种是直接一次性全部拿出,会很占内存第二种使用生成器,一次就生成一个,用多少生成多少。生成器是一个一个地指向下一个
不会回去,__next__()到哪,指针就指到哪。下一次继续获取指针指向的值。
接下来我们来看send方法,send和__next__()一样都可以让生成器执行到下一个yield.
send和__next__()的区别:
1.send和next()都是让生成器走下一次
2.send可以给上一个yield的位置传递值,不能给最后哦的一个yield发送值。在第一次执行生成器代码的时候不能用send()
注:send比__next__多了个向上一个yield传值的功能不过第一个yield跟最后一个都传不到