• python 函数的应用之迭代器、生成器


    一 迭代器
    双下方法 : 很少直接调用的方法。一般情况下,是通过其他语法触发的
    可迭代的 —— 可迭代协议 含有__iter__的方法('__iter__' in dir(数据))
    可迭代的一定可以被for循环
    迭代器协议: 含有__iter__和__next__方法
    迭代器一定可迭代,可迭代的通过调用iter()方法就能得到一个迭代器
    迭代器的好处:
    # 从容器类型中一个一个的取值,且只能取所有的数据取一次
        # 节省内存空间
    --迭代器并不会在内存中再占用一大块内存,
    而是随着循环 每次生成一个
    每次next每次给我一个
      
    迭代器的用法
    #iterator = l.__iter__()
    #iterator.__next__()

    # for i in l:
    # pass

     直接给内存地址
    print([].__iter__()) 
    # <list_iterator object at 0x003A5D70>
    print(range(10))     # range(0, 10)
    for
    #只有 是可迭代对象的时候 才能用for
    # for循环其实就是在使用迭代器
    #当我们遇到一个新的变量,不确定能不能for循环的时候,就判断它是否可迭代
    #判断是否可迭代
    print
    ('__iter__' in dir(int)) False print('__iter__' in dir(bool)) False print('__iter__' in dir(str)) True print('__iter__' in dir(list)) print('__iter__' in dir(dict)) print('__iter__' in dir(set)) print('__iter__' in dir(tuple)) print('__iter__' in dir(enumerate([]))) print('__iter__' in dir(range(1))) #只有前两个False
    dir([])
    print(dir([]))   #列表拥有的所有方法
    print(dir([].__iter__())) print(set(dir([].__iter__())) - set(dir([]))) #{'__next__', '__setstate__', '__length_hint__'}
    print(['a','bbb'].__iter__().__length_hint__())  #元素个数
    
    
    二 生成器 —— 迭代器
    生成器的本质就是迭代器
    生成器的表现形式
    生成器函数
    生成器表达式
    生成器函数:
    含有yield关键字的函数就是生成器函数
    特点:
    调用函数的之后函数不执行,返回一个生成器
    每次调用next方法的时候会取到一个值
    直到取完最后一个,在执行next会报错
    def generator():
        print(1)
        yield 'a'
    #生成器函数 : 执行之后会得到一个生成器作为返回值
    ret = generator()
    print(ret) # <generator object generator at 0x0058DB40>
    print(ret.__next__()) # 1 a
    def wahaha():
        for i in range(2000000):
            yield '娃哈哈%s'%i
    g = wahaha()
    g1 = wahaha()
    print(g.__next__())    # 娃哈哈0
    print(g1.__next__())   # 娃哈哈1
    print(g1.__next__())   # 娃哈哈0
    print(g1.__next__())   # 娃哈哈1
    
    g = wahaha()
    count = 0
    for i in g:
        count +=1
        print(i)
        if count > 50:                                
            break
    print('*******',g.__next__())
    for i in g:
        count +=1
        print(i)
        if count > 100:
            break

         

        从生成器中取值的几个方法

        # next
    # for
    # 数据类型的强制转换 : 占用内存
    g = generator()  #调用生成器函数得到一个生成器
    print(list(g))

        

    send 获取下一个值的效果和next基本一致
    只是在获取下一个值的时候,给上一yield的位置传递一个数据
    使用send的注意事项
    第一次使用生成器的时候 必须用next获取第一个值
    最后一个yield接受外部不到的值
    def averager():
        average = None
        sum = 0
        count = 0
        while True:
            num = yield average
            count+=1
            sum += num
            average = sum/count
    f = averager()
    f.__next__()
    print(f.send(10))
    print(f.send(20))
    print(f.send(30))
    示例
    预激生成器的装饰器
    def init(func):   #装饰器
        def inner(*args,**kwargs):
            g = func(*args,**kwargs)    #g = average()
            g.__next__()
            return g
        return inner
    
    @init
    def average():
        sum = 0
        count = 0
        avg = 0
        while True:
            num = yield avg
            sum += num    # 10
            count += 1    # 1
            avg = sum/count
    
    avg_g = average()   #===> inner
    ret = avg_g.send(10)
    print(ret)
    ret = avg_g.send(20)
    print(ret)
    预激生成器的装饰器

    python3 ------- (yield from 容器型元素)的用法

    def generator():
        a = 'abcde'
        b = '12345'
        for i in a:
            yield i
        for i in b:
            yield i
    # def generator():
    #     a = 'abcde'
    #     b = '12345'
    #     yield from a  
    #     yield from b
    #
    g = generator()
    for i in g:
        print(i)
    示例

     三  生成器推导式

    #生成器函数
    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))
    #生成器表达式
    
    
    laomuji=('鸡蛋%s' %i for i in range(10))#生成器表达式
    print(laomuji)
    print(next(laomuji)) #next本质就是调用__next__
    print(laomuji.__next__())
    print(next(laomuji))
    View Code


  • 相关阅读:
    libuv::线程
    libuv::定时器
    libuv::线程池
    libuv::线程同步
    ABAQUS 2017 安装后无法运行问题
    Abaqus2017安装全过程
    ModelCenter安装详解
    centos下安装Ansys 17.2的全部过程
    Jmeter压力测试分布式部署
    Centos7永久挂载iso文件
  • 原文地址:https://www.cnblogs.com/olivia2018/p/8179007.html
Copyright © 2020-2023  润新知