zoukankan      html  css  js  c++  java
  • day14.推导式与生成器

    一、列表推导式

    '''通过一行循环判断,遍历一系列数据的方式'''
    """
    推导式的语法:
        val for val in Iterable
        三种方式:
            [val for val in Iterable]
            {val for val in Iterable}
            {k:v for k,v in Iterable}
    """

    1、向列表里插入100条数据

    # 列表里面需要100条数据
    lst = []
    for i in range(1,101):
        lst.append(i)
    print(lst)

    改写成推导式

    # 基本语法
    lst = [i for i in range(1,101)]
    print(lst)

    2、[1,2,3,4,5] -> [3,6,9,12,15]

    lst = [1,2,3,4,5]
    lst_new = []
    for i in lst:
        res = i * 3
        lst_new.append(res)
    print(lst_new)

    改写成推导式

    lst = [i*3 for i in lst]
    print(lst)

    3、带有判断条件的单循环推导式 (只能是单项分支,接在for后面)

    lst = [1,2,3,4,5,6,7,8]
    lst_new = []
    for i in lst:
        if i % 2 == 1:
            lst_new.append(i)
    print(lst_new)

    改写成推导式

    # 改写成推导式
    lst = [i for i in lst if i % 2 == 1]
    print(lst)

    4、双循环推导式

    lst1 = ["李博伦","高云峰","孙致和","葛龙"]
    lst2 = ["李亚","刘彩霞","刘子豪","刘昕"]
    # "谁"❤"谁"
    lst_new = []
    for i in lst1:
        for j in lst2:
            strvar = i + "" + j
            lst_new.append(strvar)
    print(lst_new)

    改写成推导式

    # 改写成推导式
    lst = [i + "" + j for i in lst1 for j in lst2]
    print(lst)

    5、带有判断条件的多循环推导式

    lst_new = []
    for i in lst1:
        for j in lst2:
            if lst1.index(i) == lst2.index(j):
                strvar = i + "" + j
                lst_new.append(strvar)
                
    print(lst_new)

    改写成推导式

    lst = [ i + "" + j for i in lst1 for j in lst2 if lst1.index(i) == lst2.index(j) ]
    print(lst)

    6、推导式练习

    """
    (1).{'x': 'A', 'y': 'B', 'z': 'C' } 把字典写成x=A,y=B,z=C的列表推导式
    (2).把列表中所有字符变成小写  ["ADDD","dddDD","DDaa","sss"]
    (3).x是0-5之间的偶数,y是0-5之间的奇数 把x,y组成一起变成元组,放到列表当中
    (4).使用列表推导式 制作所有99乘法表中的运算
    (5)#求M,N中矩阵和元素的乘积
    # M = [ [1,2,3], 
    #       [4,5,6], 
    #       [7,8,9]  ] 
    
    # N = [ [2,2,2], 
    #       [3,3,3], 
    #       [4,4,4]  ] 
    =>实现效果1   [2, 4, 6, 12, 15, 18, 28, 32, 36]
    =>实现效果2   [[2, 4, 6], [12, 15, 18], [28, 32, 36]]
    """
    # 常规
    dic = {'x': 'A', 'y': 'B', 'z': 'C' } 
    lst = []
    for k,v in dic.items():
        strvar = k + "=" + v
        lst.append(strvar)
    print(lst)
    
    # 改写推导式
    lst = [k + "=" + v for k,v in dic.items()]
    print(lst)
    (1)
    lst = ["ADDD","dddDD","DDaa","sss"]
    lst_new = []
    # 常规
    for i in lst:
        lst_new.append(i.lower())
    print(lst_new)
    
    # 改写推导式
    lst = [i.lower() for i in lst ]
    print(lst)
    (2)
    """
    0 2 4 
    1 3 5
    """
    # 方法一
    lst = []
    for x in range(6):
        for y in range(6):
            if x % 2 == 0 and y % 2 == 1:
                lst.append((x,y))
    print(lst)
    
    lst = [(x,y) for x in range(6) for y in range(6) if x % 2 == 0 and y % 2 == 1]
    print(lst)
    
    # 方法二
    lst = []
    for x in range(6):
        if x % 2 == 0:
            for y in range(6):
                if y % 2 == 1:
                    lst.append((x,y))
    print(lst)
    lst = [(x,y) for x in range(6) if x % 2 == 0 for y in range(6) if y % 2 == 1]
    print(lst)
    (3)
    for i in range(9,0,-1):
        for j in range(1,i+1):
            print("{}*{}={:2d} ".format(i,j,i*j),end="")
        print()
        
    lst = ["{}*{}={:2d} ".format(i,j,i*j) for i in range(9,0,-1) for j in range(1,i+1) ]
    print(lst)
    (4)
    M = [[1,2,3],[4,5,6],[7,8,9]]
    N = [[2,2,2],[3,3,3],[4,4,4]]
    
    """
    M[0][0] * N[0][0] => 2
    M[0][1] * N[0][1] => 4
    M[0][2] * N[0][2] => 6
    
    M[1][0] * N[1][0] => 12
    M[1][1] * N[1][1] => 15
    M[1][2] * N[1][2] => 18
    
    M[2][0] * N[2][0] => 28
    M[2][1] * N[2][1] => 32
    M[2][2] * N[2][2] => 36
    
    外层的循环动的慢,内层的循环动的快,
    外层的循环动一次,内层的循环动3次,
    利用这个规律取出对应下标,乘积即可.
    """
    lst = []
    for i in range(3):
        for j in range(3):
            print(i,j)
            res = M[i][j] * N[i][j]
            lst.append(res)
    print(lst)
    
    # 改写推导式[效果一]
    lst = [M[i][j] * N[i][j] for i in range(3) for j in range(3)]
    print(lst)
    
    # 改写推导式[效果二]
    
    # 1 . 先遍历出三个空列表
    # lst = [  [] for i in range(3)  ]   =>  [ [],[],[] ]
    # 2 . 把空列表中的数据在通过推导式算出所有内容
    lst = [ [M[i][j] * N[i][j] for j in range(3)]  for i in range(3) ]
    print(lst)
    
    """
    常规写法:
    M = [[1,2,3],[4,5,6],[7,8,9]]
    N = [[2,2,2],[3,3,3],[4,4,4]]
    lst2 = []
    for i in range(3):
        lst = []
        for j in range(3):
            lst.append( M[i][j] * N[i][j] )
        lst2.append(lst)
    print(lst2)
    """
    (5)

    二、集合推导式

    """
    案例:
        满足年龄在18到21,存款大于等于5000 小于等于5500的人,
        开卡格式为:尊贵VIP卡老x(姓氏),否则开卡格式为:抠脚大汉卡老x(姓氏)    
        把开卡的种类统计出来
    """
    listvar = [
        {"name":"刘鑫炜","age":18,"money":10000},
        {"name":"刘聪","age":19,"money":5100},
        {"name":"刘子豪","age":20,"money":4800},
        {"name":"孔祥群","age":21,"money":2000},
        {"name":"宋云杰","age":18,"money":20}
    ]

    常规写法

    setvar = set()
    for i in listvar:
        if 18 <= i["age"] <= 21 and  5000 <= i["money"] <= 5500:
            res = "尊贵VIP卡老" + i["name"][0]
        else:
            res = "抠脚大汉卡老" + i["name"][0]
        setvar.add(res)
    print(setvar)

    改写成集合推导式

    # {三元运算符 + 推导式}
    setvar = { "尊贵VIP卡老" + i["name"][0] if 18 <= i["age"] <= 21 and  5000 <= i["money"] <= 5500 else "抠脚大汉卡老" + i["name"][0] for i in listvar }
    print(setvar)

    三、字典推导式

    """
    enumerate(iterable,[start=0])
    功能:枚举 ; 将索引号和iterable中的值,一个一个拿出来配对组成元组放入迭代器中
    参数:
        iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
        start:  可以选择开始的索引号(默认从0开始索引)
    返回值:迭代器
    """
    from collections import Iterator
    lst = ["东邪","西毒","南帝","北丐"]
    
    # 基本使用
    it = enumerate(lst)
    print(isinstance(it,Iterator))

    for + next

    # for + next
    for i in range(4):
        print(next(it))
    
    # (0, '东邪')
    # (1, '西毒')
    # (2, '南帝')
    # (3, '北丐')

    list

    """start可以指定开始值,默认是0"""
    it = enumerate(lst,start=1)
    print(list(it))
    
    #[(1, '东邪'), (2, '西毒'), (3, '南帝'), (4, '北丐')]

    enumerate 形成字典推导式 变成字典

    dic = { k:v for k,v in enumerate(lst,start=1) }
    print(dic)
    
    # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}

    dict 强制变成字典

    dic = dict(enumerate(lst,start=1))
    print(dic)
    # {1: '东邪', 2: '西毒', 3: '南帝', 4: '北丐'}

    四、zip

    """
    zip(iterable, ... ...)
        功能: 将多个iterable中的值,一个一个拿出来配对组成元组放入迭代器中
        iterable: 可迭代性数据 (常用:迭代器,容器类型数据,可迭代对象range) 
    返回: 迭代器
    
    特征: 如果找不到对应配对的元素,当前元素会被舍弃
    """
    # 基本使用
    lst1 = ["aa","bb","cc","dd"]
    lst2 = ["qq","ww","ee"]
    lst3 = ["zz","xx"]
    # it = zip(lst1,lst2)
    it = zip(lst1,lst2,lst3)
    print(isinstance(it,Iterator))
    print(list(it))
    """
    True
    [('aa', 'qq'), ('bb', 'ww'), ('cc', 'ee')]
    [('aa', 'qq', 'zz'), ('bb', 'ww', 'xx')]
    """

    1、zip 形成字典推导式 变成字典

    lst1 = ["晏国彰","刘子涛","郭凯","宋云杰"]
    lst2 = ["刘有右柳翔","冯雍","孙志新"]
    dic = { k:v for k,v in zip(lst1,lst2) }
    print(dic)
    
    # dict 强制变成字典
    dic = dict(zip(lst1,lst2))
    print(dic)

    五、生成器表达式

    """
    #生成器本质是迭代器,允许自定义逻辑的迭代器
    
    #迭代器和生成器区别:
        迭代器本身是系统内置的.重写不了.而生成器是用户自定义的,可以重写迭代逻辑
    
    #生成器可以用两种方式创建:
        (1)生成器表达式  (里面是推导式,外面用圆括号)
        (2)生成器函数    (用def定义,里面含有yield)
    """
    from collections import Iterator,Iterable
    # 生成器表达式
    gen = (i*2 for i in range(1,11))
    print(isinstance(gen,Iterator))
    
    # next 
    res = next(gen)
    print(res)
    
    # for 
    for i in gen:
        print(i)
    
    # for + next
    gen = (i*2 for i in range(1,11))
    for i in range(3):
        res = next(gen)
        print(res)
    
    # list
    print("<=====>")
    res = list(gen)
    print(res)

    六、生成器函数

    """
    # yield 类似于 return
    共同点在于:执行到这句话都会把值返回出去
    不同点在于:yield每次返回时,会记住上次离开时执行的位置 , 下次在调用生成器 , 会从上次执行的位置往下走
               而return直接终止函数,每次重头调用.
    yield 6 和 yield(6) 2种写法都可以 yield 6 更像 return 6 的写法 推荐使用
    """

    1、生成器函数的基本语法

    # 定义一个生成器函数
    def mygen():
        print(111)
        yield 1
        
        print(222)
        yield 2
        
        print(333)
        yield 3
    
    # 初始化生成器函数,返回生成器对象,简称生成器
    gen = mygen()
    print(isinstance(gen,Iterator))
    
    # 使用next调用
    res = next(gen)
    print(res)
    res = next(gen)
    print(res)
    res = next(gen)
    print(res)
    # res = next(gen) error
    # print(res)
    """
    代码解析:
    初始化生成器函数 -> 生成器(通过next调用)
    第一次调用生成器
    res = next(gen) => print(111) yield 1 保存当前代码状态14行,并将1这个值返回 print(1) ,等待下一次调用
    第二次调用生成器
    res = next(gen) => 从上一次保存的状态14行继续向下执行
    print(222) yield 2 保存当前代码状态17行,并将2这个值返回 print(2) ,等待下一次调用
    第三次调用生成器
    res = next(gen) => 从上一次保存的状态17行继续向下执行
    print(333) yield 3 保存当前代码状态20行,并将3这个值返回 print(3) ,等待下一次调用
    第四次调用生成器
    因为没有更多yield返回数据了,所以直接报错.
    """
    代码解析

    2、代码优化

    def mygen():
        for i in range(1,101):
            yield "该球衣号码是{}".format(i)
    # 初始化生成器函数 -> 生成器        
    gen = mygen()
    
    # for + next 调用数据
    for i in range(50):
        res = next(gen)
        print(res)
    print("<====>")
    for i in range(30):
        res = next(gen)
        print(res)

    3、send用法

    """
    ### send
    # next和send区别:
        next 只能取值
        send 不但能取值,还能发送值
    # send注意点:
        第一个 send 不能给 yield 传值 默认只能写None
        最后一个yield 接受不到send的发送值
        send 是给上一个yield发送值    
    """
    def mygen():
        print("process start")
        res = yield 100
        print(res,"内部打印1")
        
        res = yield 200
        print(res,"内部打印2")
        
        res = yield 300
        print(res,"内部打印3")
        print("process end")
    
    # 初始化生成器函数 -> 生成器
    gen = mygen()
    # 在使用send时,第一次调用必须传递的参数是None(硬性语法),因为第一次还没有遇到上一个yield
    '''第一次调用'''
    res = gen.send(None) #<=> next(gen)
    print(res)
    '''第二次调用'''
    res = gen.send(101) #<=> next(gen)
    print(res)
    '''第三次调用'''
    res = gen.send(201) #<=> next(gen)
    print(res)
    '''第四次调用, 因为没有更多的yield返回数据了,所以StopIteration'''
    """
    # 代码解析:
    初始化生成器函数,返回生成器对象
    第一次调用时,
    print("process start")
    res = yield 100  记录当前代码状态81行,返回100,等待下一次调用
    res = 100 print(100)
    
    第二次调用时,
    把101 发送给上一个yield保存的状态81行 res = 101 从81行继续往下走
    print(101,"内部打印1")
    res = yield 200  记录当前代码状态84行,返回200,等待下一次调用
    res = 200 print(200)
    
    第三次调用时,
    把201 发送给上一个yield保存的状态84行 res = 201 从84行继续往下走
    print(201,"内部打印2")
    res = yield 300  记录当前代码状态87行,返回300,等待下一次调用
    res  = 300 print(300)
    """
    代码解析

    4、yield from : 将一个可迭代对象变成一个迭代器返回

    def mygen():
        yield from ["马生平","刘彩霞","余锐","晏国彰"]
        
    gen = mygen()
    print(next(gen))
    print(next(gen))
    print(next(gen))
    print(next(gen))

    5、用生成器描述斐波那契数列

    """1 1 2 3 5 8 13 21 34 ... """
    """
    yield 1
    a,b = b,a+b = 1,1
    
    yield 1
    a,b = b,a+b = 1,2
    
    yield 2
    a,b = b,a+b = 2,3
    
    yield 3
    a,b = b,a+b = 3,5
    
    yield 5
    ....
    
    """
    
    def mygen(maxlen):
        a,b = 0,1
        i = 0
        while i < maxlen:
            yield b
            a,b = b,a+b
            i+=1
        
    # 初始化生成器函数 -> 生成器
    gen = mygen(10)
    
    for i in range(3):
        print(next(gen))

    七、练习

    """
    者  创建于 4天前
    # 1.用推导式写如下程序
    (1)构建如下列表:[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
    (2)lst = ['alex', 'WuSir', '老男孩', '神秘男孩'] 将lst构建如下列表:['alex0', 'WuSir1', '老男孩2', '神秘男孩3']
    (3)构建如下列表:[(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]
    (4)求出50以内能被3整除的数的平方,并放入到一个列表中。
    (5)M = [[1,2,3],[4,5,6],[7,8,9]], 把M中3,6,9组成新列表
    (6)构建如下列表:['python1期', 'python2期', 'python3期', 'python4期', 'python6期', 'python7期', 'python8期', 'python9期', 'python10期']
    (7)过滤掉长度小于3的字符串列表 , 并转换成大写字母
    (8)除了大小王,里面有52项,每一项是一个元组,请返回如下扑克牌列表[('红心','2'),('草花','J'), …('黑桃','A')] 
    
    # 2.用推导式写如下程序
    lst1 = {
            '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}             
            ]
        }
    将lst1 转化成如下lst2:
    lst2 = [
        [1517991992.94, 100], 
        [1517992000.94, 200], 
        [1517992014.94, 300], 
        [1517992744.94, 350], 
        [1517992800.94, 280]
    ]
    
    # 3.读取一个文件所有内容,通过生成器调用一次获取一行数据.
    # 4.将普通求和函数改写成yield写法
    def add(a,b):                     
        return a + b
    """
    print([i * 2 for i in range(10)])
    1 (1)
    print([j + str(i) for i in range(4) for j in lst if i == lst.index(j)])
    1 (2)
    print([(i, i + 1) for i in range(6)])
    1(3)
    print([i * i for i in range(50) if i % 3 == 0])
    1(4)
    # 方法一
    print([j for i in m for j in i if i.index(j) == 2])
    # 方法二-
    print([i[2] for i in m])
    1(5)
    print(['python' + str(i) + '' for i in range(1, 11)])
    1(6)
    lst = ['41', 'ra', 'da', '456', 'das']
    print([i.upper() for i in lst if len(i) >= 3])
    1(7)
    lst = ['红心', '红桃', '黑桃', '草花']
    print([(i, j) for j in range(1, 14) for i in lst])
    1(8)
    lst1 = {
            '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}
            ]
        }
    
    ret = [[lst1['Values'][i]['timestamp'],lst1['Values'][i]['values']]  for i in range(5)]
    print(ret)
    2
    with open('1.txt',mode='r+',encoding='utf-8') as f:
        res = f.readlines()
    print(res)
    def func1():
        for i in range(len(res)):
            yield res[i]
    
    ret = func1()
    print(next(ret))
    print(next(ret))
    print(next(ret))
    3
    def add(a,b):
        yield a+b
    res = add(1,2)
    print(res.__next__())
    4
    # 第1题
    def func():
        return [lambda x : i*x for i in range(4)]
    
    res = [m(2) for m in func()]
    print(res)
    # (1) 1号正确
    [lambda x : i*x       for i in range(4)]
    
    # (2) 不存在的
    # [    lambda x :          i*x for i in range(4)     ]
    # def func(x):
        # return i*x for i in range(4)
    
    # func(10)
    
    
    # def func(x):
        # return [i*x for i in range(4)]
    
    # lst = i for i in range(10)
    
    
    def func():
        return [lambda x : i*x    for i in range(4)]
    
    def func():
        lst = []
        for i in range(4):
            # 定义函数
            def func2(x):
                return i*x
            lst.append(func2)
            
        return lst
    
    # lst = func()
    # print(lst)
    """
    [<function func.<locals>.func2 at 0x0000014F4FCE3E18>, 
    <function func.<locals>.func2 at 0x0000014F4FCE3C80>, 
    <function func.<locals>.func2 at 0x0000014F4FCE3D08>, 
    <function func.<locals>.func2 at 0x0000014F4FCE3D90>
    ]
    
    (1) 在定义函数的时候,不会去执行函数当中的代码块,只有在调用函数的时,才执行.
    (2) i这个变量被闭包函数func2使用 生命周期被延长了,暂时不释放,当调用时,i此刻为3,直接调用.
    """
            
    
    # 在遍历列表时候,分别拿出4个函数,进行调用m(2)
    res = [m(2) for m in func()] # 6  6 6 6 
    # func2(2) 0*2 1 * 2 2 * 2 3*2
    print(res,"<===>")
    
    for i in range(4):
        print(i)
    
    # for循环遍历结束时 , i = 3
    print(i)
    View Code
    # 第2题
    def add(a,b):                     #普通求和函数
        return a + b
    def test():                       #生成器函数
        for i in range(4):
            yield i
            
    g=test()
    for n in [2,10]:
        g=(add(n,i) for i in g)
    print(list(g))
    # 第2题
    def add(a,b):                     #普通求和函数
        return a + b
    def test():                       #生成器函数
        for i in range(4):
            yield i
            
    g=test()
    for n in [2,10]:
        # (1) 生成器表达式 (2) 生成器函数
        g=(add(n,i) for i in g)
    
    # print(list(g))
    
    
    # (1) 等循环结束之后,在打印n,结果是10
    print("<====>")
    for n in [2,10]:
        print(n)
    
    print(n)
    
    # (2) 循环里面定义了2次生成器
    # 第一次
    g=(add(n,i) for i in g) # g = (0,1,2,3) n=10
    g = (10 11 12 13)
    
    # 第二次
    g=(add(n,i) for i in g) # g = (10,11,12,13) n=10
    g = (20,21,22,23)
    
    [20,21,22,23]
    
    """
    定义生成器,里面的代码时不执行的
    只有在调用生成器的时候,里面的代码才执行
    for / for + next / next / list 
    """
    View Code
  • 相关阅读:
    决策树
    flask数据库的迁移
    flask的查询,一对多,多对多
    django的验证码
    第一讲:python环境配置(python2.7+python3.7)
    pytest
    【TS】-类型兼容性
    HTML--src和href的区别
    JS--为什么null是对象?
    JS--null和undefined的区别
  • 原文地址:https://www.cnblogs.com/kongxiangqun/p/13362388.html
Copyright © 2011-2022 走看看