zoukankan      html  css  js  c++  java
  • 生成器和生成器函数,推倒式

    一. 生成器和生成器函数

    1. 生成器.

      生成器实质就是迭代器.  在python中有三种方式来获取生成器: 1. 通过生成器函数 2. 通过各种推导式来实现生成器 3. 通过数据的转换也可以获取生成器

    def f1():
        print('hello,world')
        return 'good'
    
    def f2():
        print('hello,world')
        yield 'good'  #把return换成yield就是生成器
    print(f1())  #hello,world   good
    print(f2())  #<generator object f2 at 0x0000027BD3169390>

      运行的结果和上面不一样, 是因为函数中存在了yield. 那么这个函数就是一个生成器函数. 这个时候再执行这个函数的时候, 就不再是函数的执行了. 而是获取这个生成器,生成器的本质是迭代器. 所以可以直接执行__next__()来执行生成器.

    def f():
        print('茉莉花')
        yield '歌曲'
        print('走出非洲')
        yield '电影'
        print('雷雨')
        yield '话剧'
        print('妈妈咪呀')
        yield '音乐剧'
    g = f()  #函数不会执行,只会获得函数的生成器
    print(g.__next__())  #函数执行到第一个yield,和return一样,yield也有返回值,但不会结束函数.
    # 茉莉花
    # 歌曲
    print(g.__next__())  #继续执行下一个yield
    # 走出非洲
    # 电影
    print(g.__next__())
    # 雷雨
    # 话剧
    print(g.__next__())
    # 妈妈咪呀
    # 音乐剧
    print(g.__next__())  #最后一个yield执行完毕,继续__next__,会报错:StopIteration 
     

       send和__next__()一样都可以让生成器执行到下一个yield, send还能给上一个yield赋值,所以第一个不能用send,最后一个也不要传值.

    def f():
        print('茉莉花')
        a = yield '歌曲'  #把yield赋值给a
        print('走出非洲')
        b = yield '电影'
        print('雷雨')
        c = yield '话剧'
        print('妈妈咪呀')
        d = yield '音乐剧'
    g = f()  #获取生成器
    print(g.__next__())  #第一个必须要用__next__,不能用send()
    print(g.send(1))  #从左边的a开始执行,到下一个yield结束.把1的值传给a
    print(g.send(2))  #从左边的b开始执行,到下一个yield结束.把2的值传给b
    print(g.send(3))  #从左边的c开始执行,到下一个yield结束.把3的值传给c
    # print(g.send(4))  #从左边的d开始执行,把4的值传给d,无法找到下一个yield.结果会报错.所以最后不要用send()传值

      生成器可以使用for循环来循环获取内部的元素:

    def f():
        print('茉莉花')
        yield '歌曲'
        print('走出非洲')
        yield '电影'
        print('雷雨')
        yield '话剧'
        print('妈妈咪呀')
        yield '音乐剧'
    g = f()
    for el in g:
        print(el)
    # 茉莉花
    # 歌曲
    # 走出非洲
    # 电影
    # 雷雨
    # 话剧
    # 妈妈咪呀
    # 音乐剧

    二. 推倒式

    1. 列表推导式

      语法: lst = [最终结果 for 变量 in 可迭代对象 if 条件]

    # 1. 获取1-50内能被3整除的数
    lst1 = [i for i in range(1,51) if i % 3 == 0]
    print(lst1)  #[3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48]
    
    # 2. 50以内能被3整除的数的平方
    lst2 = [i*i for i in range(1,51) if i % 3 == 0]
    print(lst2)  #[9, 36, 81, 144, 225, 324, 441, 576, 729, 900, 1089, 1296, 1521, 1764, 2025, 2304]
    
    # 3. 寻找名字中带有两个e的⼈的名字
    names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,
    'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]
    lst3 = [name for first in names for name in first if name.count("e") == 2]
    print(lst3)  #['Jefferson', 'Wesley', 'Steven', 'Jennifer']

    2. 生成器表达式

      语法: gen = (最终结果 for 变量 in 可迭代对象 if 条件)

    #10以内的偶数
    gen = (i for i in range(11) if i%2==0)
    print(gen)  #<generator object <genexpr> at 0x000001BC2BB29390>
    print(gen.__next__())  #0
    print(gen.__next__())  #2
    print(gen.__next__())  #4
    print(gen.__next__())  #6
    print(gen.__next__())  #8
    print(gen.__next__())  #10

      成器表达式和列表推导式的区别:

      (1). 列表推导式比较耗内存. 一次性加载. 生成器表达式几乎不占用内存. 使用的时候才分配和使用内存

      (2). 得到的值不一样. 列表推导式得到的是一个列表. 生成器表达式获取的是一个生成器. 

    # 生成器的惰性机制
    def func():
        print(111)
        yield  222
    g = func()  #生成器g
    g1 = (i  for i in  g)  #生成器g1,但g1的数据来源是g
    g2 = (i  for i in  g1)  #生成器g2,但g2的数据来源是g1
    
    print(list(g))  #获取g中的数据. 这时func()才会被执行. 打印111.获取到222. g完毕
    # 111
    # [222]
    print(list(g1))  #获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1也就没有数据了
    #[]
    print(list(g2))  #获取g2中的数据. g2的数据来源是g1. 但是g1没有数据. g2也就没有数据.  
    #[]

      注意:深坑==> 生成器. 要值得时候才拿值.

    3. 字典推倒式

    #把lst1的值作为key,与之相对应的lst2的值作为value
    lst1 = ["jack", "tom", "jason", "steve"]
    lst2 = ['singer', "dancer", "cook", "writer"]
    dic = { lst1[i]:lst2[i] for i in range(len(lst1))}
    print(dic)  #{'jack': 'singer', 'tom': 'dancer', 'jason': 'cook', 'steve': 'writer'}

    4. 集合推倒式

       集合推导式可以帮我们直接⽣生成一个集合. 集合的特点: ⽆无序, 不重复. 所以集合推导式自带去重功能

    lst = [1,2,1,3,4,5,6,3,3,12,10,5]
    s = {i for i in lst}
    print(s)  #{1, 2, 3, 4, 5, 6, 10, 12}

      总结:

      推导式有, 列表推导式, 字典推导式, 集合推导式, 没有元组推导式

      生成器表达式: (结果 for 变量量 in 可迭代对象 if 条件筛选)    

      生成器表达式可以直接获取到生成器对象. 生成器对象可以直接进行for循环. 生成器具有惰性机制.

    无限的我,现在才开始绽放,从东边的第一缕阳光到西边的尽头
  • 相关阅读:
    问题 I: 夫子云游
    问题 H: 小k的简单问题
    问题 G: 圆桌上的晚餐
    问题 F: 超超的自闭意思
    promise与aysnc 与EventProxy
    node的实践(项目三)
    node的实践(项目二)
    node不懂的方法的使用
    github
    node的实践(项目一)
  • 原文地址:https://www.cnblogs.com/huangqihui/p/9330866.html
Copyright © 2011-2022 走看看