day13-迭代器及生成器

iterable:可迭代的;iterator:迭代器;

print(dir([ ]))  #打印出列表所拥有的所有方法;

可迭代协议:只要含有__iter__方法的都是可迭代的。

迭代器协议:含有__iter__方法和__next__方法的就是迭代器。

对可迭代的对象调用__iter__方法就可以生成一个迭代器,for循环其实就是在使用迭代器。

迭代器的好处:

1、可以在容器类型中一个一个取值,会把所有的值都取到;

2、可以节省内存空间;

生成器

生成器函数:

只要含有yield关键字的函数都是生成器函数,yield功能和return功能类似,但不会结束函数。

调用生成器函数不会得到返回的具体的值,而是得到一个迭代器。

 1 import time
 2 def generator1():
 3     a=1
 4     print('定义了变量a')
 5     yield a
 6     b=2
 7     print('定义了变量b')
 8     yield b
 9 g1=generator1()
10 print(g1) #打印g1发现g1只是生成器
11 print(g1.__next__())
12 print('-'*20)  #华丽的分割线
13 time.sleep(3) #sleep看清执行过程
14 print(g1.__next__())
View Code

 send方法

1、取值功能上和next相同

2、只是取下一个数据时,给上一个yield位置传递一个函数

注意事项:

  #第一次使用生成器的时候,是用next取值;

  #最后一个yield不能接收外部的值

计算移动平均值__预激协程的装饰器

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

@wrap1
def averager():
    count=0
    sum1=0.0
    aver=None
    while True:
        term=yield aver
        sum1+=term
        count+=1
        aver=sum1/count

g=averager()
#next(g),在装饰器中调用了next方法
print(g.send(10))
print(g.send(20))
print(g.send(30))
View Code

 yield from 可迭代对象a

a迭代产生的每个值都直接传递给生成器的调用者

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

list1=['egg%s'% i for i in range(10) ]    #列表解析式
print(list1)

laomuji=('egg%s'% i for i in range(10))  #生成器表达式
for i in laomuji:
    print(i)
View Code

1、将列表推导器的[]换成()就变成了生成器表达式。
2、列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

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

原文地址:https://www.cnblogs.com/geng-xiaoqiaoliushui/p/10275142.html