迭代器和生成器

一、迭代器

1、可迭代协议

     迭代:可以将某个数据集内的数据“一个挨着一个的取出来”,就叫做迭代

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

     可以被for循环的都是可迭代的,要想可迭代,内部必须有一个__iter__方法。

2、迭代器

迭代器大部分都是在Python的内部去使用的,我们直接拿来用就行了。
迭代器: 内置__iter__和__next__方法

 

别管是一个迭代器还是一个可迭代对象,都可以使用For循环遍历
迭代器出现的原因 帮你节省内存

 

迭代器的特点:
可以有for循环,可以节省内存,只能用一次

拥有__iter__方法和__next__方法

  例如:iter(range()),iter(str),iter(list),iter(tuple),iter(dict),iter(set),reversed(list_o),map(func,list_o),filter(func,list_o),file_o

 

from collections import Iterator
print(isinstance(range(100000000),Iterator)) >>验证range执行之后得到的结果不是一个迭代器

二、生成器

1、Python中提供的生成器:

 

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

 

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

2、生成器Generator:

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

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

3、生成器函数 :

def func():
    print('aaaa')
    a=1
    yield a
    print('bbbb')
    b=2
    yield b
ret=func()
print(next(ret))
print(next(ret))
初识生成器
def averager():
    total=0
    day=0
    averag=0
    while True:
        day_num=yield  averag
        total+=day_num
        day+=1
        averag=total/day
avg=averager()
# avg.send()
next(avg)
print(avg.send(10))
print(avg.send(15))
print(avg.send(15))
移动平均值
def produce():
    """生产衣服"""
    for i in range(2000000):
        yield "生产了第%s件衣服"%i

product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g:         #要一批衣服,比如5件
    print(i)
    num +=1
    if num == 5:
        break
示例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))
移动平均值2
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、使用生成器的优点:

延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。

 

 

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

总结:

1.把列表解析的[]换成()得到的就是生成器表达式

2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

sum(x ** 2 for x in xrange(4))

而不用多此一举的先构造一个列表:

sum([x ** 2 for x in xrange(4)]) 

 

原文地址:https://www.cnblogs.com/yifugui/p/7274208.html