---恢复内容开始---
迭代器 生成器
迭代器:
1, 什么是迭代器协议
① dir(被测对象) 如果它含有 __iter__,那这个对象叫做可迭代对象,遵循可迭代协议。
② 可迭代对象:iterable 可以转换 迭代器(如何实现:都像内部定义一个 __iter__()方法)
迭代器(iterator)遵循迭代器协议
2, 迭代器
1,只含有__iter__方法的数据是课迭代的对象
l = [1,2,3,4] print('__iter__' in dir(l))
2,含有__iter__方法,并且含有__next__方法的数据是迭代器。
print(dir([1,2].__iter__()))
3, 迭代器的意义:
① 迭代器节省内存
② 迭代器有惰性机制
③ 迭代器不能反复,一直向下执行。
4, for 循环机制
for 可以循环有: 字符串,列表,元祖,字典,集合,说明它们都是可以被迭代的。
在for循环中,就是在内部调用了__next__方法才能取到一个一个的值。
那接下来我们就用迭代器的next方法来写一个不依赖for的遍历。
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)
这是一段会报错的代码,如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。
这个时候,我们就要使用异常处理机制来把这个异常处理掉
l = [1,2,3,4] l_iter = l.__iter__() while True: try: item = l_iter.__next__() print(item) except StopIteration: break
那现在我们就使用while循环实现了原本for循环做的事情,我们是从谁那儿获取一个一个的值呀?是不是就是l_iter?好了,这个l_iter就是一个迭代器。
1,内部含有__iter__方法,他会将可迭代对象先转化成迭代器,然后在调用__next__方法。
2,它有异常处理方法
range 它是可迭代对象,不是迭代器
验证range 是不是迭代器
print('__next__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__ print('__iter__' in dir(range(12))) #查看'__next__'是不是在range()方法执行之后内部是否有__next__
from collections import Iterable from collections import Iterator
print(isinstance(range(100000000),Iterable)) print(isinstance(range(100000000),Iterator)) #验证range执行之后得到的结果不是一个迭代器
生成器:
1, 生成器的本质就是迭代器,迭代器,生成器是python自己用python代码写的迭代器
2,生成器的特点:
①可以用生成器函数写
②可以用各种推导式构建迭代器
③可以通过数据转化
3,return 和 yield 的区别
① return 返回给调用者值,并结束此函数
② yiled 返回给调用者值,并将指针停留在当前位置
import time def genrator_fun1(): a = 1 print('现在定义了a变量') yield a b = 2 print('现在又定义了b变量') yield b g1 = genrator_fun1() print('g1 : ',g1) #打印g1可以发现g1就是一个生成器 print('-'*20) #我是华丽的分割线 print(next(g1)) time.sleep(1) #sleep一秒看清执行过程 print(next(g1))
4, send :
1,给上一个 yiled 整体发送一个值
2, send 不能给最后一个 yiled 发送值
3, 获取第一个值的时候,不能用 send 只能用 next
def generator(): print(123) content = yield 1 print('=======',content) print(456) yield2 g = generator() ret = g.__next__() print('***',ret) ret = g.send('hello') #send的效果和next一样 print('***',ret)
---恢复内容结束---