首页 > 代码库 > 迭代器与生成器
迭代器与生成器
一.迭代和可迭代协议
迭代:简单来说,就是可以将数据集内的数据一个挨一个取出来
可以被迭代要满足的要求就是可迭代协议,要想可迭代,内部必需有一个_iter_方法
二.迭代器
迭代器遵循协议:必须有_iter_、_next_方法
迭代器的_next_方法(不依赖for循环实现遍历)
1 l = [1,2,3,4] 2 l_iter = l.__iter__() 3 item = l_iter.__next__() 4 print(item) 5 item = l_iter.__next__() 6 print(item) 7 item = l_iter.__next__() 8 print(item) 9 item = l_iter.__next__() 10 print(item) 11 item = l_iter.__next__() 12 print(item)
由于元素只有四个,所以迭代不到数据会报错(用异常处理机制解决)
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: 8 break
range() (可迭代的对象,但不是一个迭代器)
三.生成器
两种迭代器:
一种是调用方法直接返回的,一种是可迭代对象通过执行_iter_方法,迭代器有个好处就是可以节省内存
我们自己写的实现迭代器功能的东西就叫迭代器
python中提供的生成器
1.生成器函数:常规函数定义,但是使用的是yield返回语句而不是return语句返回的结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次从它离开的地方继续执行。
2.生成器表达式:类似于列表推导,但是生成器返回按需产生结果的一个对象,而不是一次产生一个结果列表
生成器本质:迭代器,自带了iter和next方法,不用我们去实现
特点:惰性运算,开发者自定义
四.生成器函数
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
1 import time 2 def genrator_fun1(): 3 a = 1 4 print(‘现在定义了a变量‘) 5 yield a 6 b = 2 7 print(‘现在又定义了b变量‘) 8 yield b 9 10 g1 = genrator_fun1() 11 print(‘g1 : ‘,g1) #打印g1可以发现g1就是一个生成器 12 print(‘-‘*20) #我是华丽的分割线 13 print(next(g1)) 14 time.sleep(1) #sleep一秒看清执行过程 15 print(next(g1))
生成器监听文件输入的内容
1 import time 2 3 def tail(filename): 4 f = open(filename) 5 f.seek(0, 2) #从文件末尾算起 6 while True: 7 line = f.readline() # 读取文件中新的文本行 8 if not line: 9 time.sleep(0.1) 10 continue 11 yield line 12 13 tail_g = tail(‘tmp‘) 14 for line in tail_g: 15 print(line)
计算移动平均值
1 def averager(): 2 total = 0.0 3 count = 0 4 average = None 5 while True: 6 term = yield average 7 total += term 8 count += 1 9 average = total/count 10 11 12 g_avg = averager() 13 next(g_avg) 14 print(g_avg.send(10)) 15 print(g_avg.send(30)) 16 print(g_avg.send(5)) 17
预激协程装饰器
1 def init(func): #在调用被装饰生成器函数的时候首先用next激活生成器 2 def inner(*args,**kwargs): 3 g = func(*args,**kwargs) 4 next(g) 5 return g 6 return inner 7 8 @init 9 def averager(): 10 total = 0.0 11 count = 0 12 average = None 13 while True: 14 term = yield average 15 total += term 16 count += 1 17 average = total/count 18 19 20 g_avg = averager() 21 # next(g_avg) 在装饰器中执行了next方法 22 print(g_avg.send(10)) 23 print(g_avg.send(30)) 24 print(g_avg.send(5)) 25 26 预激协程的装饰器
yield from
1 def gen1(): 2 for c in ‘AB‘: 3 yield c 4 for i in range(3): 5 yield i 6 7 print(list(gen1())) 8 9 def gen2(): 10 yield from ‘AB‘ 11 yield from range(3) 12 13 print(list(gen2())) 14 15 yield from
总结:列表解析和生成器表达式相比,后者更节省内存
迭代器与生成器