• 迭代器和生成器


    一、迭代器

    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)]) 

     

  • 相关阅读:
    java MVC设计模式探究——mvc在JAVA应用程序中的应用
    datagridview 的Columns 点击列标题 禁止排序
    组合键事件
    对一段视频,采帧(总结)
    datagridview中加入checkbox列,全选问题
    微软的RDLC报表(转)
    Linq to sql直接执行sql语句(转)
    获取当月的第1天
    AxWindowsMediaPlayer的详细用法
    DataSet
  • 原文地址:https://www.cnblogs.com/yifugui/p/7274208.html
Copyright © 2020-2023  润新知