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))
  • 相关阅读:
    HDU 3572 Task Schedule(拆点+最大流dinic)
    POJ 1236 Network of Schools(Tarjan缩点)
    HDU 3605 Escape(状压+最大流)
    HDU 1166 敌兵布阵(分块)
    Leetcode 223 Rectangle Area
    Leetcode 219 Contains Duplicate II STL
    Leetcode 36 Valid Sudoku
    Leetcode 88 Merge Sorted Array STL
    Leetcode 160 Intersection of Two Linked Lists 单向链表
    Leetcode 111 Minimum Depth of Binary Tree 二叉树
  • 原文地址:https://www.cnblogs.com/whc6/p/14105300.html
Copyright © 2011-2022 走看看