zoukankan      html  css  js  c++  java
  • 08-Python基础之迭代器与生成器

    迭代器

    可迭代协议:只要含有__iter__方法的都是可迭代的,只要是能被for循环的数据类型 就一定拥有__iter__方法

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

    迭代器的好处:

       从容器类型中一个一个的取值,会把所有的值都取到

       节省内存空间,迭代器并不会在内存中再占用一大块内存,而是随着循环 每次生成一个,每次next每次给我一个

    注意:

    __next__()方法当取完时候会报错。
    print(dir([]))   #告诉我列表拥有的所有方法,其他的只要改想知道的类型就可以了

    生成器

    生成器 ----也是一种迭代器,即含有__next__和__iter__方法

    生成器函数

    #只要含有yield关键字的函数都是生成器函数
    # yield不能和return共用且需要写在函数内
    def generator():
        print(1)
        yield 'a'
    # #生成器函数 : 执行之后会得到一个生成器作为返回值
    ret = generator()    #得到一个内存地址
    print(ret)          #<generator object generator at 0x000002774525D830>,通过next取值,一个yield返回一个值
    print(ret.__next__())   #打印   1    a

     生成器函数进阶:

    def generator():
        print('123456789*')
        contend = yield 1
        print('==========',contend)
        print('*987654321')
        yield
    
    g = generator()
    print(g.__next__())
    #send的效果和next一样,都是往下执行,只是在获取下一个值的时候,给上一yield的位置传递一个数据
    #使用send的注意事项
        # 第一次使用生成器的时候 是用next获取下一个值
        # 最后一个yield不能接受外部的值
    g.send('hello')
    # print(g.__next__())                思考:打印的是什么?
    
    # 获取移动平均值
    # 10 20 30 10
    # 10 15 20 17.5
    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()
    avg_g.__next__()
    avg1 = avg_g.send(10)
    avg1 = avg_g.send(20)
    print(avg1)
    
    '''
    重点思考代码的执行过程?
    '''
    
    #预激生成器的装饰器
    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)
    '''
    重点思考执行过程?然后能写下来
    '''
    View Code

    生成器表达式

    '''
    把列表解析的[]换成()得到的就是生成器表达式
    '''
    #列表解析
    li = [i*2 for i in range(5)]        #内存占用大,机器容易卡死
    print(li)               #li = [0, 2, 4, 6, 8]
    print(type(li))         #<class 'list'>
    #生成器表达式
    li = (i*2 for i in range(5))   #几乎不占内存
    print(li)                #<generator object <genexpr> at 0x000002BC67B8D930>
    print(type(li))         #<class 'generator'>

    各种推导式:

    #列表推导式
    multiples = [i for i in range(30) if i % 3 is 0]  #30以内所有能被3整除的数
    
    # def squared(x):
    #     return x*x
    multiples = [i*i for i in range(30) if i % 3 is 0]  #30以内所有能被3整除的数的平方
    print(multiples)
    
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
    print([name for lst in names for name in lst if name.count('e') >= 2])  # 注意遍历顺序,这是实现的关键
    
    #字典推导式
    
    mcase = {'a': 10, 'b': 34}    #将一个字典的key和value对调
    mcase_frequency = {mcase[k]: k for k in mcase}
    print(mcase_frequency)
    
    #集合推导式
    squared = {x**2 for x in [1, -1, 2]}
    print(squared)
    # Output: set([1, 4])
    自学课程参照老男孩全栈视频
  • 相关阅读:
    20110603 本日跌的股票之后一段时间轻易不要碰
    一日三省
    火电排污新标准年内出台 撬动千亿脱硝市场
    20082011大股东增持专题
    收评:5月24日资金流向(摘自益盟)
    2011年中期业绩预增前20家公司
    2011大股东十大增持概念股全景图
    放不下期货
    从众是通向地狱最廉价的门票
    在ASP.NET中获取Get方式和Post方式提交的数据
  • 原文地址:https://www.cnblogs.com/chenrongjin/p/10017426.html
Copyright © 2011-2022 走看看