迭代器和生成器

 

 

迭代器和生成器

1、什么是迭代器和可迭代对象

(1) 可迭代对象

定义:内部实现了__iter__方法,即可迭代协议。可迭代协议的定义非常简单,可以被迭代要满足的要求就叫做可迭代协议。

(2)迭代器

定义:代器遵循迭代器协议:必须拥有__iter__方法和__next__方法。

补充:迭代器是python内置的,如果一个对象是可迭代的但不一定是迭代器。

迭代器有两种:一种是调用方法直接返回的,一种是可迭代对象通过执行iter方法得到的,迭代器有的好处是可以节省内存。

举例:

print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__
print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__

from collections import Iterator
print(isinstance(range(100000000),Iterator))  #验证range
可迭代对象与迭代器

2、初识生成器

定义:我们自己写的这个能实现迭代器功能的东西就叫生成器。

(1)python中提供的生成器

1、生成器函数

特点:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行。

2、生成器表达式

特点:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表。

(2)生成器generator

本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

特点:惰性运算,开发者自定义。

3、生成器函数

(1)定义:一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。

import time
def genrator_fun1():
    a = 1
    print('现在定义了a变量')
    yield a
    b = 2
    print('现在又定义了b变量')
    yield b

g1 = genrator_fun1()
print('g1 : ',g1)       #打印g1可以发现g1就是一个生成器
print('-'*20)   #我是华丽的分割线
print(next(g1))
time.sleep(1)   #sleep一秒看清执行过程
print(next(g1))
生成器函数

(2)生成器的应用
1、监听文件

import time


def tail(filename):
    f = open(filename)
    f.seek(0, 2) #从文件末尾算起
    while True:
        line = f.readline()  # 读取文件中新的文本行
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail('tmp')
for line in tail_g:
    print(line
监听文件

2、计算移动平均值

def init(func):  #在调用被装饰生成器函数的时候首先用next激活生成器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)
        next(g)
        return g
    return inner

@init
def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average
        total += term
        count += 1
        average = total/count


g_avg = averager()
# next(g_avg)   在装饰器中执行了next方法
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))
计算移动平均值

3、yield from的应用

def gen1():
    for c in 'AB':
        yield c
    for i in range(3):
        yield i

print(list(gen1()))

def gen2():
    yield from 'AB'
    yield from range(3)

print(list(gen2()))
yield from 的应用

4、列表推导式和生成器表达式

列表推导式

print([i for i in range(10) if i%2==1])
列表推导式

生成器表达式

print((i for i in range(10) if i%2==1))
生成器表达式

总结:1、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存。
           2、列表解析式返回的是一个结果,而生成器表达式返回的是一个生成器。

使用生成器的优点:

1.延迟计算,一次返回一个结果

2.、提高代码可读性

 

原文地址:https://www.cnblogs.com/hzauq/p/7294742.html