• DAY12 生成器初始与列表生成式


    初识生成器

      通过前面学习的迭代器,我们知道,迭代器十分节省内存。如果在某些情况下,我们也需要节省内存,就只能自己写,我们自己用python代码实现的迭代器就称为生成器。

      生成器:生成器就是自己用python代码写的迭代器,生成器的本质就是迭代器。

      (1)因为本质是迭代器,所以自带了__iter__方法和__next__方法。

      (2)特点:惰性运算,开发者自定义。

      python中提供的两种方法构建生成器:

      (1)生成器函数:与普通函数的return不同,而是使用yield关键字。yield语句一次返回一个结果,在每个结果中间挂起函数,以便下次从它离开的地方再次运行。

      (2)生成式推导式:类似于列表推导式,但是不是一次性构建一个列表,而是按需每次返回一个值。

    构建生成器方式一:生成器函数

      一个包含yield关键字的函数就称为生成器函数。与普通函数的return不同,函数一遇到return就会结束函数并给函数的执行者返回值;但是yield不会结束函数,而是返回值给'生成器对象.__next__()',每次获得可迭代对象,就会推动函数的进行。

    #一。回顾普通函数与return
    def func1(x):
        x +=1
        return x         #函数遇到return关键字,就会结束函数并返回值给函数的执行者。
    
    res = func1(6)   #函数的执行命令,并且接受函数的返回值
    print(res)
    
    
    #二。生成器函数,yield关键字。
    def gen1(x):
        x +=1
        print(1111)
        yield x               #带有yield关键字的函数,称为生成器函数。
        print(2222)
        yield x
    
    gen_obj =  gen1(5)         #此时这个就不是函数的执行者了,是生成器的对象
    print(gen_obj)
    >>><generator object gen1 at 0x000001DFD052FE08> 
    print(gen_obj.__next__())
    >>>                              #一个yield关键字,会把值返回个一个next,并且把函数挂起。
    1111
    6
    print(gen_obj.__next__())    #第二个生成器对象,会从挂起处继续向下执行,遇到第二个yield返回。
    >>>
    2222
    6
    print(gen_obj.__next__())   #生成器本质就是迭代器,只能一路走到黑,不能回头,所以报错。
    >>>
    StopIteration
    
    
    #生成器范例二:
    def func1(x):
        x +=1
        yield x
        x +=3
        yield x
        x +=5
        yield x
    g1 = func1(5)              #g1为生成器对象
    print(g1.__next__())    #一个yield对应一个next,yield把值返回,所以x为6     
    print(g1.__next__())    #一个yield对应一个next,yield把值返回,所以6+3=9   
    print(g1.__next__())    #一个yield对应一个next,yield把值返回,所以9+5=14
    
    '''因为生成器本质就是迭代器,所以符合迭代协议'''
    for i in g1:
        print(i)
    >>>
    6
    9
    14
    

      总结1:yield与return的区别?

      答:return结束函数,给函数的执行者返回值。yield不会结束函数,一个next调用对应一个yield,yield把值返回给"生成器对象.__next__()"

      总结2:生成器与迭代器的差别?

      答:从内存级别来看,迭代器需要可迭代对象来进行转化,可迭代对象非常占内存;生成器直接创建,不需要转换,从本质上就节省内存。

    send与next

      send : send与next在取值上是一样的,执行一个yield方法。但是send可以给上一个yield传递值。

      谨记:(1)第一次取值永远都是next。

         (2)最后一个yield永远也得不到send传的值。

    #一。send与next在取值上是一样的,都是对应一个yield关键字。
    def func1():
        print(1)
        yield 6
        print(2)
        yield 7
        print(3)
        yield 8
    
    g1 = func1()
    print(next(g1))
    print(g1.send('alex'))
    print(next(g1))
    >>>
    1
    6
    2
    7
    3
    8
    
    #二。但是send可以给上一个yield传递值
    def func1():
        count = yield 6
        print(count)
        yield 7
        yield 8
    
    g1 = func1()
    print(next(g1))     #遇到next调用一个yield,此时yield返回值为6,所以next(g1)为6,yield无实体值,
                                 所以count为None
    g1.send('alex')     #遇到send取值与next一致,对一个yield,但是会给上一个yield赋值,所以 
                                 count=‘alex
    print(next(g1))     #同上。
    >>>
    6
    alex
    8

    构建生成器方式二:生成器推导式

       前提知识:列表生成式/列表推导式

      1.一行代码几乎搞掂需求简单的任何列表,方便。

      2.不易排错,不建议超过三次循环。

    #一。循环模式 [ 变量 for 变量 in iterable ]
    list = [x for x in range(101)]
    print(list)
    >>>
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
    
    l2 = [i**2 for i in range(1,11)]
    print(l2)
    >>>
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    
    
    #二。筛选模式  [ 加工后的变量  for 变量 in Iterable  if  条件]
    '''30以内被3整除的数'''
    print([ i for i in range(1,30) if i%3==0])
    >>>
    [3, 6, 9, 12, 15, 18, 21, 24, 27]
    
    '''30以内被3整除的数的平方'''
    print([ i**2 for i in range(1,30) if i%3==0])
    >>>
    [9, 36, 81, 144, 225, 324, 441, 576, 729]
    
    '''找出嵌套列表中名字含有两个'e'的所有名字'''
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
             ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    
    print([j for i in names for j in i if j.count('e') >= 2])
    >>>
    ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
    

      生成器推导式

      1.十分简单,只需要把列表推导式[]换成()即可

      

    # 通过生成式推导式构建生成器generator
    
    g1 = (i for i in range(1,10000))
    print(g1)
    print(g1.__next__())
    print(g1.__next__())
    print(g1.__next__())
    print(g1.__next__())
    >>>
    <generator object <genexpr> at 0x00000253C09DFE08>
    1
    2
    3
    4
    

      

      

      

  • 相关阅读:
    Git for Windows安装和基本设置
    Intellij IDEA 快捷键整理
    mongoDb 命令
    CSS隐藏元素 display、visibility、opacity的区别
    推荐一款可以丰富博文GIF免费录制工具——GifCam
    html5新媒体播放器标签video、audio 与embed、object
    HTML5 video视频字幕的使用和制作
    网页中嵌入百度影音播放器的代码
    JS中的排序算法-冒泡排序解析
    深入了解opacity和rgba
  • 原文地址:https://www.cnblogs.com/hebbhao/p/9505701.html
Copyright © 2020-2023  润新知