迭代器和生成器
迭代器概念
可迭代协议
可迭代协议: 就是内部实现了__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
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题或建议,请联系上述邮箱,非常感谢。

浙公网安备 33010602011771号