python 迭代器和生成器
一、迭代器
1.什么是可迭代对象:字符串、列表、元祖、字典、集合都可以被for循环,说明他们都是可迭代的。
1 s = 'ailaohuyou' 2 print(dir(s)) 3 li = [1,2,3,4,5] 4 print(dir(li)) 5 dic = {'1':'haha','2':'xixi'} 6 tu = ('jk',123,'sdf',456) 7 print(dir(tu)) 8 set1 = {123,'ihao',456,'haha'} 9 print(dir(set1))
什么是可迭代对象:内部含有__iter__方法的对象
isinstance(判断是否是可迭代的,返回True)
1 from collections import Iterable 2 3 4 l = [1, 2, 3, 4] 5 t = [1, 2, 3, 4] 6 d = [1, 2, 3, 4] 7 s = [1, 2, 3, 4] 8 q = 'jin' 9 o = (1,'asd','kl') 10 k = {'key1':123,'key2':'jkslfa'} 11 print(isinstance(l,Iterable)) 12 print(isinstance(t,Iterable)) 13 print(isinstance(d,Iterable)) 14 print(isinstance(s,Iterable)) 15 print(isinstance(q,Iterable)) 16 print (isinstance(o,Iterable)) 17 w= isinstance(k,Iterable)
1.2可迭代协议
我们现在是从结果分析原因,能被for循环的就是“可迭代的”,但是如果正着想,for怎么知道谁是可迭代的呢?
假如我们自己写了一个数据类型,希望这个数据类型里的东西也可以使用for被一个一个的取出来,那我们就必须满足for的要求。这个要求就叫做“协议”。
可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。
1.3 迭代器
什么叫做迭代器?迭代器英文意思是iterator
可迭代对象转化成迭代器:可迭代对象__iter__()--迭代器
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
for循环,能遍历一个可迭代对象,他的内部到底进行了什么?
将可迭代对象转化成迭代器。(可迭代对象.__iter__())
内部使用__next__方法,一个一个取值。
加了异常处理功能,取值到底后自动停止
1 l1 = [1,2,3,4] 2 l1_obj = l1.__iter__() 3 print('__iter__'in dir(l1_obj))#true 4 print('__next__'in dir(l1))#flase 5 print('__next__'in dir(l1_obj))#true
l1 = [1,2,3,4,6] l1_iter = l.__iter__()#将可迭代的转化成迭代器 item = l1_iter.__next__() print(item) item = l1_iter.__next__() print(item) item = l1_iter.__next__() print(item) item = l1_iter.__next__() print(item)
用while循环模拟for循环:
for循环中存在__next__中的机制,但是不存在报错机制
1 l = [1,2,3,4] 2 l_iter = l.__iter__() 3 while True: 4 try: 5 item = l_iter.__next__() 6 print(item) 7 except StopIteration:#stopiteration是错误名称,不写默认全部错误 8 break
1.4迭代器的好处
1.节省内存
2.满足惰性机制
3.不能反复取值(不可逆)
二、生成器
生成器本质上就是迭代器,生成器的产生构造
1.生成器的函数构造
2.生成器的推导式
3.数据类型的转化
1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从他离开的地方继续执行
2.2生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值,直到函数执行的结束。
1 def func1(): 2 print(111) 3 print(222) 4 print(333) 5 yield(555) 6 yield(666) 7 yield(777) 8 9 g = func1() 10 print(g)#<generator object func1 at 0x000001D7E9B84728> 11 print(g.__next__())#111,222,333,555 12 print(g.__next__())#111,222,333,555,666 13 print(g.__next__())#111,222,333,555,666,777
1.函数中只要有yield那他就不是一个函数,而是一个生成器
2.g称为生成器对象
2.3
工厂给学校做200件校服
1 def func1(): 2 3 for i in range(1,201): 4 print('这是第%d件衣服' %i) 5 6 func1() 7 8 9 10 11 12 def func2(): 13 for i in range(1,201): 14 yield('这是第%d件衣服' %i) 15 g= func2() 16 17 for i in range(50): 18 g.__next__() 19 20 21 for i in range(150): 22 print(g.__next__())
2.4send
1 def generator(): 2 print(1,2,3) 3 content = yield 1 4 print('======',content) 5 print(456) 6 yield 2 7 8 g = generator() 9 ret = g.__next__() 10 print('*****',ret) 11 12 ret = g.send('hello') 13 print('*****',ret)
send 获取下一个值的效果和next基本一致 只是在获取下一个值的时候,给上一yield的位置传递一个数据 使用send的注意事项 第一次使用生成器的时候 是用next获取下一个值 最后一个yield不能接受外部的值
2.4生成器导出式
列表推导式:用列表推导式能构建的任何列表,用别的都可以构建
一行搞定,简单,但不易排错。
1 l = [] 2 for i in range(1,11,1): 3 s = ('python第%d期'%i) 4 l.append(s) 5 print (l) 6 7 8 9 10 l2 = ['python第%d期'%i for i in range(1,12)] 11 print(l2)
循环模式
经过加工的i for i in 可迭代对象
sheng