• 巨蟒python全栈开发-第12天 生成器函数 各种推导式 yield from


    一.今日主要内容总览(重点)

    1.生成器(目的:帮助我们创建对象)
    (1)生成器的本质就是迭代器
    (2)一个一个的创建对象
    (3)创建生成器的方式:
    1.生成器函数
    2.通过生成器表达式来获取生成器
    3.类型转换(看不到)

    2.生成器函数(重点)
    (1)生成器函数中包含 yield关键字,返回数据和return差不多
    return会立即结束和这个函数的执行
    yield 可以分段的执行一个函数

    (2)大坑(五星重点):
      生成器函数在执行的时候返回生成器,而不是直接执行次函数

    (3)能向下执行的两个条件:
    __next__(),执行到下一个yield
    send(),执行到下一个yield,给上一个yield位置传值

    (4)所有的生成器都是迭代器,都可以直接使用for循环
    都可以使用list()函数来获取到生成器内所有的数据

    (5)生成器中记录的是代码而不是函数的运行
    def func():
    print('我的天哪')

    yield '宝宝'
    gen=func() #创建生成器,此时运行会把生成器函数中的代码记录在内存
    当执行到__next__(),运行此空间中的代码,运行到yield结束

    (6)生成器
    优点:节省内存,生成器本身就是代码,几乎不占用内存
    特点:惰性机制,只能向前,不能反复

    3.各种推导式(诡异)
    列表推导式 [结果 for 循环 if]
    字典推导式 {结果(k,v) for 循环 if}
    集合推导式 {结果(k) for 循环 if}

    4.生成器表达式(重点)
    (结果 for循环 if)

    二.今日内容大纲

    1.生成器函数

    2.各种推导式

    3.yield from

    三.内容详解

    1.生成器函数

    (1)

    def func():
        print('我叫周润发')
        return '林志玲'        #return
    ret=func()
    print('返回值是:',ret)
    '''
    结果:
    我叫周润发
    返回值是: 林志玲
    '''

    (2)

    注意:
    函数中包含了yield,次函数就是生成器函数
    大坑:生成器函数运行之后,产生一个生成器,而不是运行函数
    def func():
        print('我叫周润发')
        yield '林志玲'        #yield表示返回,不会终止函数的执行
        print('宝宝去干嘛了???')
        yield '宝宝回来了'
        print('大冬瓜,你好')
        # yield '没了'
    ret=func()      #执行函数,但是此时没有运行函数
    #此时,我们拿到的是生成器ret
    print('返回值是:',ret)      #返回值是: <generator object func at 0x000002286D7CCF68>
    #
    # #执行到下一个yield
    print(ret.__next__())       #第一次执行__next__此时函数才开始执行
    print(ret.__next__())       #第二次执行__next__此时函数才开始执行,执行到下一个yield
    #
    # print(ret.__next__())     #如果最后一句没有  ''yield '没了' '',报错原因是:StopIteration
                                # 这句话开始报错,并且'大冬瓜,你好'也不会打印
    
    '''
    结果:
    返回值是: <generator object func at 0x000001B57FC2CF68>
    我叫周润发
    林志玲
    宝宝去干嘛了???
    宝宝回来了
    '''

    (2-1)

    def func():
        print('我叫周润发')
        yield '林志玲'        #yield表示返回,不会终止函数的执行
        print('宝宝去干嘛了???')
        yield '宝宝回来了'
        print('大冬瓜,你好')
        yield '没了'
    ret=func()
    
    #第一种
    for i in ret:
        print(i)
    
    #第二种
    while 1:
        try:
            k=ret.__next__()
            print(k)
        except StopIteration:
            break

    (3)

    买衣服, JACK JONES 10000件衣服
    当数据量很大,有用不了,怎么办,用一个拿一个

    (3-1)直接放入列表中10000件
    def buy():
        lst=[]
        for i in range(10000):
            lst.append("衣服%s"%i)
        return lst
    k=buy()
    print(k)

    (3-2)取20件,简单版本

    def buy():
        for i in range(10000):
            yield '衣服%s' %i
    lst=buy()           #生成器或者迭代器的好处:节省内存
    # print(lst.__next__())
    # print(lst.__next__())
    # print(lst.__next__())
    #
    for i in range(20):
        print(lst.__next__())

    (3-3)#想拿多少件拿多少件//重磅题目

    def buy():
        for i in range(10000):
            yield '衣服%s' %i
    re=buy()
    while 1:
        n=input('请输入需要提取的衣服数量:').strip()
        m=0
        for i in re:
            print(i)
            m += 1
            if m==int(n):
                break
        s=input('是否还要继续取衣服:').strip()
        if s=='':continue
        else:break

    (4)

    def buy():
        for i in range(10000):
            yield '衣服%s' %i
    lst=buy()
    
    # 方法一:
    for yifu in lst:    #迭代器.__next__()
        print(yifu)   #注意这里是没有加括号的
    
    # 方法二:   #超级重点
    print(lst)
    lst=list(lst)   #将地址强转成了列表里的内容
    print(lst)

    (5)

    (5-1)

    def func():
        print('韭菜盒子')
        a=yield '韭菜鸡蛋'
        print('a',a)
        b=yield '韭菜西红柿'
        print('b',b)
        c=yield '火烧'
        print('c',c)
    gen=func()
    #
    print(gen.__next__())
    print(gen.__next__())
    print(gen.__next__())
    结果:
    结果:
    韭菜盒子
    韭菜鸡蛋
    a None
    韭菜西红柿
    b None
    火烧

    (5-2)

    功能介绍
    send() =>__next__()
    send() 可以给上一个yield传值
    def func():
        print('韭菜盒子')
        a=yield '韭菜鸡蛋'
        print('a=',a)
        b=yield '韭菜西红柿'
        print('b=',b)
        c=yield '火烧'
        print('c',c)
    gen=func()
    
    # # 方法一:
    print(gen.__next__())    # 第一个位置用send没有任何意义
    #结果:
    # 韭菜盒子
    # 韭菜鸡蛋
    print(gen.send('篮球'))    # 给上一个yield位置传值
    #结果:
    # a=篮球
    # 韭菜西红柿
    print(gen.send('足球'))
    #结果:
    # b=足球
    # 火烧
    # print(gen.send('排球'))#这句话再传入就会报错了,因为后边没有接收了

    (5-3)
    def eat():
         print("我吃什么啊")
         a = yield "馒头"
         print("a=",a)
         b = yield "⼤饼"
         print("b=",b)
         c = yield "⾲菜盒⼦"
         print("c=",c)
         yield "GAME OVER"
    
    gen = eat() # 获取⽣成器
    
    ret1 = gen.__next__()               #我吃什么啊
    print(ret1)                         #馒头
    ret2 = gen.send("胡辣汤")          #a= 胡辣汤
    print(ret2)                         #⼤饼
    ret3 = gen.send("狗粮")             #b= 狗粮
    print(ret3)                         #⾲菜盒⼦
    ret4 = gen.send("猫粮")             #c= 猫粮
    print(ret4)                         #GAME OVER
    
    

    2.各种推导式

    (1)

    #生成列表:python1期 =>python18期
    
    lst=[]
    for i in range(1,19):
        lst.append('python%s期'%i)
    print(lst)

    (2)

    列表推导式语法: [结果 for循环 if 条件]

    不要着急写结果,先写循环,再写结果
    lst=['python%s期'%i for i in range(1,19)]   #循环一次拿一次
    print(lst)
    
    '''
    结果:
    ['python1期', 'python2期', 'python3期', 'python4期', 'python5期', 'python6期',
     'python7期', 'python8期', 'python9期', 'python10期', 'python11期', 'python12期', 
     'python13期', 'python14期', 'python15期', 'python16期', 'python17期', 'python18期']
    '''

    (3)练习

    # 练习1 生成列表,类似于表中装好的数据是 1-100之间所有的偶数的平方
    
    lst=[i**2 for i in range(1,101) if i%2==0]
    print(lst)
    
    # 练习二:筛选出列表中姓张的同学,lst=['张无忌','吴奇隆','张诗诗','范冰冰','张翠山']
    #法一
    lst=['张无忌','吴奇隆','张诗诗','范冰冰','张翠山']
    li=[i for i in lst if i[0]=='']
    print(li)
    #法二
    li=[i for i in lst if i.startswith('')]
    print(li)
    
    # 练习三:寻找名字中带有两个e的人的名字
    
    names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven','Joe'],
            ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
    li=[ii for i in names for ii in  i if ii.count('e')>=2]
    print(li)
    #老师写法
    li=[ii for i in names for ii in  i if ii.count('e')==2]
    print(li)

    (4)#字典推导式

    # 语法: {结果(key:value) for循环 if条件}
    lst=[11,22,33]      #结果{0:11,1:22,2:33}
    dic={i:lst[i] for i in range(len(lst))}
    print(dic)
    
    # 练习: {"主食": "炒面", "副食": "小拌菜", "汤":"疙瘩汤"}
    # 把字典的key和value互换,生成新字典
    dic={"主食": "炒面", "副食": "小拌菜", "":"疙瘩汤"}
    di={v:k for k,v in dic.items()}     #这个题目当时没有想出来,不要受上一个题目影响
    print(di)

    (5)集合推导式

    集合推导式{k for循环 if 条件}

    没有元组推导式
    g=(i for i in range(10))    #生成器表达式是一次性的,如果想在迭代完,继续用,再写一遍
    print(g)                  #<generator object <genexpr> at 0x0000000009E573B8>
    print(g.__next__())     #执行10次取完,也就是再写9次
    print(g.__next__())     #第11次,StopIteration

    (6)

    #生成器函数
    def func():
        print(111)
        yield 222
        # yield 333       #就算后边有再多的yield ,也是放在第一个列表中
        # yield [1,2,3]
    
    #注意:1.惰性机制,2.只能向前
    g = func()          # 创建⽣成器g
    g1 = (i for i in g) #生成器表达式  创建了一个新的⽣成器g1. 但是g1的数据来源于g
    g = func()
    g2 = (i for i in g1) # 创建了一个新的⽣成器⽣成器g2. 来源g1
    
    #注意:在这之前,只是记录了关系,并没有工作
    
    print(g)          #<generator object func at 0x0000013452C32048>
    print(list(g)) # 获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕.
    # #list(g)直接拿没了
    #
    # print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据了
    print(list(g2)) # 和g1同理
    无论注释,倒数第一行还是注释倒数第二行,结果都是下面结果
    '''
    结果:

    <generator object func at 0x000002056A182048>
    111
    [222]
    111
    [222]

    '''
    如果都放开是
    '''

    <generator object func at 0x000002056A182048>
    111
    [222]
    111
    [222]

    []


    '''

    3.yield from

     (1)

    def func():
        # lst=['衣服%s'%i for i in range(500)]
        # yield from lst      #将列表中的每一项进行yield返回
    
        for i in range(500):      #等价于上边两行,上边相当于yield from中的列表中的一行
            yield '衣服%s'%i
    
    gen=func()
    print(gen.__next__())
    print(gen.__next__())
    '''
    总结:
    1.list=列表推导式
      yield from list
    2.for 循环
      yield 值
    1和2等价
    '''

    (2)先拿第一个,再拿第二个

    def func():
        lst=['衣服%s'%i for i in range(2)]
        yield from lst
    
        lst = ['python%s' % i for i in range(15)]
        yield from lst
    gen=func()
    print(gen.__next__())
    print(gen.__next__())
    print(gen.__next__())
    print(gen.__next__())
    print(gen.__next__())
    '''
    结果:
    衣服0
    衣服1
    python0
    python1
    python2
    '''

    今日作业:

    2,用列表推导式做下列小题
    (1)
    (1)过滤掉长度小于3的字符串列表,并将剩下的转换成大写字母
    '''
    lis=['penchengchegn','wusir','sir','we']
    li=[i.upper() for i in lis if len(i)>=3 ]
    print(li)
    '''

    (2)

    求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元祖列表
    '''
    li = [(x,x+1) for x  in  range(6) if x%2==0]
    
    # 全排列,注意这个题目的写法
    li = [(x,y) for x  in  range(6) if x%2==0 for y in range(6) if y%2==1]
    print(li)
    '''

    (3)

    求M中3,6,9组成的列表M = [[1,2,3],[4,5,6],[7,8,9]]
    M = [[1,2,3],[4,5,6],[7,8,9]]
    li=[i[2] for i in M]
    print(li)               # 结果:[3, 6, 9]
    
    M = [[1,2,3],[4,5,6],[7,8,9]]
    li=[[i for i in range(1,4)],[i for i in range(4,7)],[i for i in range(7,10)]]
    print(li)               #结果:[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    
    M = [[1,2,3],[4,5,6],[7,8,9]]
    lst = [ a for i in M for a in i if a ==i[2]]
    print(lst)

    (4)

    求出50以内能被3整除的数的平方,并放入到一个列表中。
    '''
    li=[i**2 for i in range(50) if i%3==0]
    print(li)
    '''

    (5)

    构建一个列表:['python1期', 'python2期', 'python3期', 'python4期', 'python6期', 'python7期', 'python8期', 'python9期', 'python10期']
    '''
    li=['python%s期'%i for i in range(1,11)]
    print(li)
    ''')

    (6)

    构建一个列表:[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
    '''
    li=[(x,x+1) for x in range(6)]
    print(li)
    '''

    (7)

    构建一个列表:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    '''
    li=[i for i in range(19) if i%2==0]
    print(li)
    '''

    (8)

    有一个列表l1 = ['alex', 'WuSir', '老男孩', '太白']将其构造成这种列表['alex0', 'WuSir1', '老男孩2', '太白3']
    l1 = ['alex', 'WuSir', '老男孩', '太白']
    li=[l1[s]+str(s) for s in range(4)]
    print(li)

    (9)

    题目

    有以下数据类型:
    x = {
        'name':'alex',
        'Values':[{'timestamp':1517991992.94,
             'values':100,},
            {'timestamp': 1517992000.94,
            'values': 200,},
            {'timestamp': 1517992014.94,
             'values': 300,},
            {'timestamp': 1517992744.94,
             'values': 350},
            {'timestamp': 1517992800.94,
             'values': 280}
            ],}
    将上面的数据通过列表推导式转换成下面的类型:
    [[1517991992.94, 100], [1517992000.94, 200], [1517992014.94, 300], [1517992744.94, 350], [1517992800.94, 280]]

    答案:

    x = {
        'name':'alex',
        'Values':[{'timestamp':1517991992.94,
             'values':100,},
            {'timestamp': 1517992000.94,
            'values': 200,},
            {'timestamp': 1517992014.94,
             'values': 300,},
            {'timestamp': 1517992744.94,
             'values': 350},
            {'timestamp': 1517992800.94,
             'values': 280}
            ],}
    
    li=[[i['timestamp'],i['values']] for i in x['Values']]
    print(li)
  • 相关阅读:
    react_瞎敲
    linux 删除类似文件
    mysql建立dblink 视图,无法查询到数据的问题
    Guava-Retrying 请求重试机制
    Command line is too long. Shorten command line for WebServiceUtilsTest.callMethod or also for JUnit default
    @Scheduled 定时任务注解不能运行
    jq拷贝表单$("#searchForm").clone(true),无法将select2数据value拷贝的问题
    正则表达式的lookaround(lookahead/lookbehind)以及密码复杂度检查
    MYSQL列的长度,NUMERIC_PRECISION和COLUMN_TYPE
    Qira-docker安装与使用
  • 原文地址:https://www.cnblogs.com/studybrother/p/10105570.html
Copyright © 2020-2023  润新知