zoukankan      html  css  js  c++  java
  • python学习第11天----生成器、生成器函数、推导式、生成器表达式

    1.生成器(generator)

      生成器的本质就是迭代器

    1)生产器的三种生成方法

    ①通过生成器函数

    ②通过生成器表达式创建生成器

    ③通过数据转换

    2.生成器函数

    1)函数中包含了关键字yield,当前这个函数就不再是普通的函数了,而是一个生成器函数;此执行这个函数(即调用),只会获取到生成器,而不是去执行这个函数

    def func():
        print("九尾妖狐")
        yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
    func()      #不再是执行函数,而是通过func()来创建一个生成器
    print(func())
    输出:
    <generator object func at 0x000001A3D0380AF0>
    View Code

    #生成器的本质是迭代器,所以可以以迭代器的方式使用生成器

    def func():
        print("九尾妖狐")
        yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
    g = func()      #不再是执行函数,而是通过func()来创建一个生成器
    print(g.__next__())
    输出:
    九尾妖狐
    阿狸
    View Code

    2)return是直接返回函数的结果,结束函数的调用;yield也是返回结果,但会继续往下执行,可以让函数分段执行

    def func():
        print("九尾妖狐")
        yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
        print("远古巫灵")
        yield "泽拉斯"
        print("无双剑姬")
        yield "菲奥娜"
    g = func()      #不再是执行函数,而是通过func()来创建一个生成器
    print(g.__next__())
    print(g.__next__())
    print(g.__next__())
    输出:
    九尾妖狐
    阿狸
    远古巫灵
    泽拉斯
    无双剑姬
    菲奥娜
    View Code

    #注:生成器函数中,最后一个yield后面的内容,会被执行到,但是会报错(StopIteration),所以在最后一个yield之后,是不写代码的(最后一个yield后,再进行__next__()会报错)

    3.send方法

    1)__next__()方法和send()方法的共同点和区别

    ①共同点:__next__()可以让生成器向下执行一次;send()也可以让生成器向下执行一次

    def func():
        print("九尾妖狐")
        yield "阿狸"      #retuen换成了yield,表示次函数是一个生成器函数
        print("远古巫灵")
        yield "泽拉斯"
        print("无双剑姬")
        yield "菲奥娜"
    g = func()      #不再是执行函数,而是通过func()来创建一个生成器
    print(g.__next__())
    print(g.send(1))
    print(g.__next__())
    输出:
    九尾妖狐
    阿狸
    远古巫灵
    泽拉斯
    无双剑姬
    菲奥娜
    View Code

    ②区别:send()该可以给上一个yield传一个值;但是不能给最后一个yield发送值,否则会报错,在第一次执行生成器的时候,只能使用__next__(),不能使用send(), 因为此时没有上一个yield

    def func():
        print("九尾妖狐")      #黄色区域表示第一个__next__()的执行
        a = yield "阿狸"      #send传入的值赋值给了a
        print(a)            #a的值由send传入
        print("远古巫灵")
        b = yield "泽拉斯"     #蓝色区域为send()的执行
    print(b)
        print("无双剑姬")
        c = yield "菲奥娜"      #灰色区域为下一个send()执行
    g = func()      #不再是执行函数,而是通过func()来创建一个生成器
    print(g.__next__())
    print(g.send(666))
    print(g.send(999))
    输出:
    九尾妖狐
    阿狸
    666
    远古巫灵
    泽拉斯
    999
    无双剑姬
    菲奥娜
    View Code

    例:将生成器转换对象转化为一个列表

    def func():
        yield 11
        yield 12
        yield 13
        yield 44
    g = func()
    lst = list(g)
    print(lst)
    输出:
    [11, 12, 13, 44]
    View Code

    4.推倒式

    1)引入:生成一个列表,里面装1-14的数据

    lst = []
    for i in range(1,15):
        lst.append("python%s" % i)
    print(lst)
    输出:
    ['python1', 'python2', 'python3', 'python4', 'python5', 'python6', 'python7', 'python8', 'python9', 'python10', 'python11', 'python12', 'python13', 'python14']
    View Code

    2)列表推导式完成上述要求

    ①语法

    [最终结果(变量) for 变量 in 可迭代对象]

    ②完成上述要求

    lst = ["python%s" % i for i in range(1,15)]
    print(lst)
    输出:
    ['python1', 'python2', 'python3', 'python4', 'python5', 'python6', 'python7', 'python8', 'python9', 'python10', 'python11', 'python12', 'python13', 'python14']
    View Code

    ③纯数字

    lst = [ i for i in range(1,15)]
    print(lst)
    输出:
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
    View Code

    ④练习:

    #获取1-100内能被3整数的数

    lst = [i for i in range(1,101) if i%2 ==0 ]
    print(lst)
    输出:
    [2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100]
    View Code

    #获取100以内能被3整除的数的平方

    lst = [i*i for i in range(1,101) if i%3==0]
    print(lst)
    输出:
    [9, 36, 81, 144, 225, 324, 441, 576, 729, 900, 1089, 1296, 1521, 1764, 2025, 2304, 2601, 2916, 3249, 3600, 3969, 4356, 4761, 5184, 5625, 6084, 6561, 7056, 7569, 8100, 8649, 9216, 9801]
    View Code

    #寻找名字中带有两个e的名字

    names = [['Tom', 'Billy', 'Jefferson' , 'Andrew' , 'Wesley' , 'Steven' ,
    'Joe'],['Alice', 'Jill' , 'Ana', 'Wendy', 'Jennifer', 'Sherry' , 'Eva']]
    lst = [name for first in names for name in first if name.count("e")==2]
    print(lst)
    输出:
    ['Jefferson', 'Wesley', 'Steven', 'Jennifer']
    View Code

    总结:其他的东西正常写,只是把最终的结果提到了前面

    5.生成器表达式

     1)生成器表达式和列表推导式的语法基本一昂,只是把[]换成了();这时候产生的就不再是一个列表,而是一个生成器

    g = (i for i in range(1,10))
    print(g)           #g为生成器对象,就生成器表达式生成
    print(g.__next__())
    print(list(g)
    输出:
    <generator object <genexpr> at 0x00000168E5FA0D00>
    1
    [2, 3, 4, 5, 6, 7, 8, 9]
    View Code

    #循环输出整个生成器

    g = (i for i in range(1,10))
    for el in g:
        print(el)
    1
    。
    。
    9
    View Code

    2)生成器表达式和列表推导式的区别

    ①列表推导式比较耗费额你存,一次性加载。生成器表达式几乎不占用内存,使用的时候才分配和使用内存

    ②得到的值不一样,列表推导式得到的是一个列表,生成器表达式获取的是一个生成器

    3)生成器的惰性机制:生成器只有在访问的时候才取值,即找它要才给你值,不找它要,就不会执行;

             同样一篮子鸡蛋,列表推导式:直接拿到一篮子鸡蛋;生成器表达式:拿到一个老母鸡,需要急待就给你下蛋

    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. 来源g1
    print(list(g)) # 获取g中的数据. 这时func()才会被执⾏. 打印111.获取到222. g完毕.
    print(list(g1)) # 获取g1中的数据. g1的数据来源是g. 但是g已经取完了. g1 也就没有数据
    print(list(g2)) #和g1同理
    输出:
    111
    [222]
    []
    []
    View Code

    6.字典推导式

    #将字典中的key和value互换

    dic = {'a':"张三",'b':"李四"}
    dic_new = {dic[key]:key for key in dic}
    print(dic_new)
    输出:
    {'张三': 'a', '李四': 'b'}
    View Code

    #将lst1列表中的值作为key;lst2列表中的值作为value,生成一个字典

    lst1 = ["LOL","CF","DNF","qqfeiche"]
    lst2 = ["英雄联盟","穿越火线","地下城与勇士","QQ飞车"]
    dic = {lst1[i]:lst2[i] for i in range(len(lst1))}
    print(dic)
    输出:
    {'CF': '穿越火线', 'LOL': '英雄联盟', 'qqfeiche': 'QQ飞车', 'DNF': '地下城与勇士'}
    View Code

    7.集合推导式

             集合推导式可以直接生成一个集合;集合的特点的是无序,不重复;所以集合推导式自带去重功能

    lst = ["九尾妖狐","远古巫灵","九尾妖狐","惩戒之箭"]
    s = {i for i in lst}      #集合推导式
    print(s)
    输出:
    {'惩戒之箭', '远古巫灵', '九尾妖狐'}
    View Code

    总结:推导式有列表推导式、字典推导式、集合推导式,但是没有元组推导式

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

             生成器表达式可以直接获取到生成器对象,生成器对象可以直接进行for许纳湖按,生成器具有惰性机制

    例:

    def add(a, b):
        return a + b
    def test():
        for r_i in range(4):
            yield r_i
    g = test()
    for n in [2, 10]:
        g = (add(n, i) for i in g)
        # g = (add(n, i) for i in add(n, i) for i in g)
        # g = (add(n, i) for i in add(n, i) for i in test())
        # g = (add(n, i) for i in add(n, i) for i in [0,1,2,3])
        # g = (add(10, i) for i in add(10, i) for i in [0,1,2,3])
        # g = (add(10, i) for i [10,11,12,13])
    
    print(list(g))
    输出:
    [20, 21, 22, 23]
    View Code

    8.练习

    1)用推导式完成:过滤掉长度小于3的字符串列表,并将剩下的转化成大写字母

    lst = ["apple","bababa","dog","pig","orange"]
    lst_new = [el.upper() for el in lst if len(el) > 3 ]
    print(lst_new)
    输出:
    ['APPLE', 'BABABA', 'ORANGE']
    View Code

    2)推导式完成:求(x,y)其中x是0-5之间的偶数,y是0-5之间的奇数组成的元组列表

    lst = [(x,y) for x in range(5) if x%2==0 for y in range(5) if y%2==1]
    print(lst)
    输出:
    [(0, 1), (0, 3), (2, 1), (2, 3), (4, 1), (4, 3)]
    View Code

    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]]
    lst = [i[2] for i in M]
    print(lst)
    输出:
    [3, 6, 9]
    View Code

    #倒着推导

    M = [3, 6, 9]
    lst = [[i-2,i-1,i] for i in M]
    print(lst)
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    View Code

    4)推导式:求出50以内能被3整除的数的平方,并放入到一个列表中

    lst = [i*i for i in range(50) if i%3==0]
    print(lst)
    输出:
    [0, 9, 36, 81, 144, 225, 324, 441, 576, 729, 900, 1089, 1296, 1521, 1764, 2025, 2304]
    View Code

    5)推导式构建一个列表[0,2,4,6,8,10,12,14,16,18]

    lst = [i for i in range(0,20,2)]
    print(lst)
    输出:
    [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    View Code
  • 相关阅读:
    我的五年百度博客文章列表
    servlet过滤器2 解决用户非法在线 filter
    flexpaper实例在浏览器无法显示的解决办法
    我的五年百度博客文章列表(带链接版)
    servlet过滤器1 解决字符集乱码 filter
    GBK和UTF8之间的战争,websphere6.1乱码解决方案
    ORACLE SQL性能优化系列 (一)
    ORACLE SQL性能优化系列 (四)
    Oracle优化SQL查询优化研究
    用SQL*Loader将Excel数据导出到Oracle
  • 原文地址:https://www.cnblogs.com/piaolaipiaoqu/p/13851521.html
Copyright © 2011-2022 走看看