迭代器和生成器

迭代器概念

可迭代协议

可迭代协议: 就是内部实现了__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)

  

 

posted @ 2020-07-24 00:57  闫世成  阅读(99)  评论(0编辑  收藏  举报