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

    一、列表推导式

    '''通过一行循环判断,遍历一系数据的方式'''
    推导式语法
        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)

    二、集合推导式

    """
    案例:
        满足年龄在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 = ["晏国彰","刘子涛","郭凯","宋云杰"]
    lst2 = ["刘有右柳翔","冯雍","孙志新"]
    lst3 = ["周鹏飞","袁伟倬"]
    # it = zip(lst1,lst2)
    it = zip(lst1,lst2,lst3)
    print(isinstance(it,Iterator))
    print(list(it))
    """
    [('晏国彰', '刘有右柳翔'), ('刘子涛', '冯雍'), ('郭凯', '孙志新')]
    [('晏国彰', '刘有右柳翔', '周鹏飞'), ('刘子涛', '冯雍', '袁伟倬')]
    """

    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)

    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'''

    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))
  • 相关阅读:
    Linux进程间通信(IPC)
    mq_setattr
    mq_getattr
    mq_unlink
    mq_receive
    mq_send
    mq_close
    POSIX消息队列
    mq_open
    C语言关键字
  • 原文地址:https://www.cnblogs.com/whc6/p/14105300.html
Copyright © 2011-2022 走看看