day13 python学习 迭代器,生成器

1.可迭代:
当我们打印

print(dir([1,2]))   在出现的结果中可以看到包含

'__iter__',  这个方法,#次协议叫做可迭代协议

包含'__iter__'方法的函数就是可迭代函数
字符串、列表、元组、字典、集合都可以被for循环,说明他们都是可迭代的


2.迭代器 iterator
l = [1,2,3,4]
l_iter = l.__iter__()  #迭代器的生成
item = l_iter.__next__()    #迭代器的使用,用此方法一一钓鱼迭代器中的数值
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
item = l_iter.__next__()
print(item)
#迭代器取值的三种方法
1.item.__next() 传统方法

2 在for循环中取值
for i in range(10):
  print(item.__next__()) #取出里边的10个值
for i in item.__next__()  #将里边所用的值在循环中取出
  print(i)


3. print(list(item)) 用 list 方法强转成列表在迭代器中取出值


这是一段会报错的代码,如果我们一直取next取到迭代器里已经没有元素了,就会抛出一个异常StopIteration,告诉我们,列表中已经没有有效的元素了。

这个时候,我们就要使用异常处理机制来把这个异常处理掉。

l = [1,2,3,4]
li=l.__iter__()
while True:
        try:
            item=li.__next__()
            print(item)
        except StopIteration:#这里要输入的是报错的内容  ,出现这个错误时执行以下内容
print('超出索引') break

3.判断是否是迭代器

print('__next__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__   当他为真时证明是可迭代的,
print('__iter__' in dir(range(12)))  #查看'__next__'是不是在range()方法执行之后内部是否有__next__   当两个结果都为True时,就是迭代器

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

4.生成器

如果在某些情况下,我们也需要节省内存,就只能自己写。我们自己写的这个能实现迭代器功能的东西就叫生成器。

Python中提供的生成器:

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

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

 

生成器Generator:

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

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

生成器函数

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

 

def func():   #这就是一个简单的生成器函数
    for i in range(1000):
        yield ('生产了%s件衣服'%i)            注意这里使用的是yield  返回数据  而不是return  
j=func()
print(j.__iter__())
print(j.__iter__())
print(j.__iter__())
import time
def func():
    with open('file3','r',encoding="utf8") as f3:
        f3.seek(0, 2)#这个位置一定要放在外边因为只有第一次是将光标放在最后,后续就不再操作了,否则
        while True:
            a=f3.read()  #如果放在它上边 while循环中,就会读不到新加的内容
            if not a:    #这里跟最后一个yield   要注意位置和条件
                time.sleep(0.1)
                continue
            yield a
g=func()
for i in g:
    print(i)
生成器监听文件,seek的位置,yield需返回的值
def everage():
    sum=0
    count=0
    average=None
    while True:  #这里一定要写,因为send这种传入后要往下走到下一个yield,所以需要循环
        a=yield average
        sum+=a
        count+=1
        average=sum/count
g=everage()
print(g.__next__())#  要先执行这一步,因为用send不能给刚启动的生成器传参数
print(g.send(12))
计算移动平均值,用send穿参数,记住在那里才能用send

 


posted on 2017-11-05 14:37  王大拿  阅读(189)  评论(0编辑  收藏  举报

导航