迭代器和生成器
迭代器概念
可迭代协议
可迭代协议: 就是内部实现了__iter__方法。
只要能被 for 循环的数据类型,就一定拥有 __iter__方法.
只要有 __iter__方法就是可迭代的.
迭代器协议
迭代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。
只要有 __next__ __iter__和 就是一个迭代器,可以通过 next 在迭代器中一个个取值.
优点 数据不会一次性加载到内存,用一个取一个.
while实现for功能
l = [1,2,3,4,5,6] iterator = l.__iter__() while 1: try: print(iterator.__next__()) except StopIteration: break
生成器概念
内部含有 yield 就是生成器函数.
生成器函数:
生成器就是我们写的函数, 但是使用 yield 语句实现而不是 return 语句返回结果. yield 语句一次返回一个结果, 在每个结果中间,挂起函数的状态,以方便下次从它离开的地方继续执行.
生成器表达式:
类列表推导式,生成器返回按需生产对象,而不是像列表一样一次构建结果.
生成器Generator:
本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)
特点:惰性运算,开发者自定义
优点:
节省内存.
代码实现
基础版本
def generator(): print(1) yield 'a' print(2) yield 'b' # 生成器函数 执行之后会得到一个生成器作为函数的返回值 ret = generator() print(ret.__next__()) for i in ret: print(i)监控
文件输入类似 tail -f
def tail(filename): with open(filename,encoding='utf-8') as f: while 1: line = f.readline() if line.strip(): yield line.strip() g = tail('file') # for i in g: # if 'python' in i: # print('****' ,i)
生成器函数进阶
send 使用效果和 yield 基本一致. 只是在获取下一个值的时候,给上一个位置传递一个数据.
第一次使用生成器的时候是用 next 获取下一个值
最后一个 yield 不能接受外部的值
def generator(): print(123) content = yield 'a' print(content) print(456) yield 'b' g = generator() ret = g.__next__() print(ret) ret = g.send('send') print(ret)
获取移动平均值
# avg = sum/count def average(): sum = 0 count = 0 avg = 0 while 1: num = yield avg sum +=num count += 1 avg = sum / count g = average() g.__next__() avg1 = g.send(10) avg2 = g.send(20) print(avg1,avg2)
预激活生成器装饰器:
def init(func): def inner(*args,**kwargs): g = func(*args,**kwargs) g.__next__() return g # 返回一个已经激活的生成器 return inner @init def average(): sum = 0 count = 0 avg = 0 while 1: num = yield avg sum +=num count += 1 avg = sum / count avg_g = average() ret = avg_g.send(100) print(ret)
yield from
def generator(): a = 'abcdefg' b = '1234567' for i in a: yield i for i in b: yield i # def generator(): # a = 'abcdefg' # b = '1234567' # yield from a # yield from b g = generator() for i in g: print(i)
作者:闫世成
出处:http://cnblogs.com/yanshicheng
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题或建议,请联系上述邮箱,非常感谢。