• 列表推导式,Python中最好的特性?可读性?


    B站|公众号:啥都会一点的研究生

    相关阅读

    整理了几个100%会踩的Python细节坑,提前防止脑血栓
    整理了十个100%提高效率的Python编程技巧,更上一层楼
    Python-列表,从基础到进阶用法大总结,进来查漏补缺
    Python-元组,从基础到进阶用法大总结及与列表核心区别,进来查漏补缺
    Python-字典,从基础到进阶用法大总结,进来查漏补缺
    Python-集合,从基础到进阶大总结,进来查漏补缺
    这些包括我在内都有的Python编程陋习,趁早改掉
    Python可变类型的坑,不要再踩了
    列表推导式,Python中最好的特性?可读性?
    订阅专栏 ===> Python

    关于推导式,可读性一直是引起较大争议的地方,我们首先看个例子

    symbols = '$¢£¥€¤'
    codes = []
    
    for symbol in symbols:
        codes.append(ord(symbol))
    # [36, 162, 163, 165, 8364, 164]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    有一点基础的都可以知道这段程序目的是从字符串构建对应的统一字符编码,但如果你会列表推导,不可否认的是它读起来更舒服

    symbols = '$¢£¥€¤'
    codes = [ord(symbol) for symbol in symbols]
    # [36, 162, 163, 165, 8364, 164]
    
    • 1
    • 2
    • 3

    如果只是用列表推导来创建新的列表,且代码较为简短,可以放心使用。若推导式的代码都有两行甚至好几行,那么就要考虑是否得用for循环代替,没有硬性规定,自己拿捏这个度

    这个例子展示的是最基本的用法,列表推导常常还会与if相结合,比如这个例子,我们想保存0-10中的偶数

    out = []
    for i in range(11):
        if i % 2 == 0:
            out.append(i)
    # [0, 2, 4, 6, 8, 10]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用推导式则可以一行搞定

    out = [i for i in range(11) if i %2 == 0]
    # [0, 2, 4, 6, 8, 10]
    
    • 1
    • 2

    紧接着,再一起来看看这个例子,我们想把原始列表中大于5的数置零,正常可能写成这样

    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    out = []
    for i in my_list:
        if i > 5:
            out.append(1)
        else:
            out.append(i)
    # [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    而若使用列表推导式依旧是一行搞定,是不是很清爽

    my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    out = [0 if i > 5 else i for i in my_list]
    # [1, 2, 3, 4, 5, 0, 0, 0, 0, 0]
    
    • 1
    • 2
    • 3

    列表推导式可以帮助我们把一个序列或者其他可迭代对象中的元素过滤或者加工,并且构造一个新的列表,虽然Python一些内置函数也可以达到这个效果,但是,可读性也将大打折扣,一起来看看这个例子

    symbols = '$¢£¥€¤'
    beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
    # [162, 163, 165, 8364, 164]
    
    • 1
    • 2
    • 3

    我们想将过滤掉unicode小于127的字符,推导式会这样做,但Python内置函数mapfilter结合也可以达到目的

    symbols = '$¢£¥€¤'
    beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))
    # [162, 163, 165, 8364, 164]
    
    • 1
    • 2
    • 3

    相信你们对这两个的可读性对比已经有了自己的答案,讲完了这些,再来看看嵌套结构,比如我们想生成二维数组,可以使用如下推导式达到目的

    matrix2d = [[j for i in range(3)] for j in range(3)]
    # [[0, 0, 0], [1, 1, 1], [2, 2, 2]]
    
    • 1
    • 2

    多维的也同样适用,此处只是展示推导式功能,如果真要用数组,还是用numpy这种库吧

    matrix3d = [[[j for i in range(3)] for k in range(3)] for j in range(3)]
    # [
    #     [[0, 0, 0], [0, 0, 0], [0, 0, 0]], 
    #     [[1, 1, 1], [1, 1, 1], [1, 1, 1]], 
    #     [[2, 2, 2], [2, 2, 2], [2, 2, 2]]
    #     ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后呢就是笛卡尔积,什么是笛卡尔积呢,笛卡儿积是一个列表,列表里的元素是由输入的可迭代类型的元素对构成的元组,用列表推导可以生成两个或以上的可迭代类型的笛卡儿积,笛卡儿积列表的长度等于输入变量的长度的乘积

    # D1 = ['A', 'B']
    # D2 = ['a', 'b']
    # Dp = [('A', 1), ('A', 2), ('A', 3), ('B', 1), ('B', 2), ('B', 3)]
    
    • 1
    • 2
    • 3

    拿个图片来说明,如图为含有4种花色和3种牌面的列表的笛卡儿积,所以这个图片对应的笛卡尔积结果是一个包含12个元素的列表,使用推导式呢就是写成如下形式

    D1 = ['A', 'K', 'Q']
    D2 = ['spades', 'hearts', 'diamonds', 'clubs']
    Cartesian_product = [(i, j) for i in D1 for j in D2]
    # [('A', 'spades'), ('A', 'hearts'), ('A', 'diamonds'), ('A', 'clubs'), ('K', 'spades'), ('K', 'hearts'), ('K', 'diamonds'), ('K', 'clubs'), ('Q', 'spades'), ('Q', 'hearts'), ('Q', 'diamonds'), ('Q', 'clubs')]
    
    • 1
    • 2
    • 3
    • 4

    其实,除开列表推导式,集合、字典也支持这种编写方式,比如这个例子我们想知道字符串中涵盖的元音字母,可以写成如下形式

    my_str = 'Hello, World!'
    vowels = {i for i in my_str if i.lower() in 'aeiou'} # {'e', 'o'}
    type(vowels) # 
    
    • 1
    • 2
    • 3

    打印类型也显示为set,下一个,这个例子呢就说明了推导式在字典中的用法,借助range快速创建一个键为数字,值为其平方的字典,注意此时其类型变成了字典

    my_dict = {i : i ** 2 for i in range(1, 6)} # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    type(my_dict) # 
    
    • 1
    • 2

    当然,大胆发挥for循环的作用,我们也可以使用推导式从现有字典创建新字典,在上个例子基础上将其值再进行平方

    my_dict = {i : i ** 2 for i in range(1, 6)} # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
    new_dict = {k: v ** 2 for (k, v) in my_dict.items()} # {1: 1, 2: 16, 3: 81, 4: 256, 5: 625}
    
    • 1
    • 2

    下一个,形如这种表达不是元组推导式,而是生成器表达式,也对上期说法做个勘误

    data = (i for i in range(6))
    type(data) # 
    
    • 1
    • 2

    **列表推导的最大作用只有一个,那就是生成列表,如果想生成其他类型的序列,生成器表达式才是更好选择。**在下一期元组专题中我会将其放在一起归纳讲解,以上就是本期的全部内容,有任何错误请在评论区进行指出,该系列会持续更新,我是啥都生,我们下期再见。

  • 相关阅读:
    电力系统强大的Gurobi 求解器的学习(Python&Matlab)
    SQL开源替代品,诞生了
    【必读要点】Pod控制器Deployment更新、回退详解
    Dive into TensorFlow系列(3)- 揭开Tensor的神秘面纱
    【6 - 完结】Sql Server - 郝斌(identity、视图、事务、索引、存储过程、触发器、游标、TL_SQL)
    写一篇nginx配置指南
    企业微信接入芋道SpringBoot项目
    第六章 SELinux
    2023最新最全【虚幻4引擎】下载安装零基础教程
    一篇关于vue的入门的详细介绍
  • 原文地址:https://blog.csdn.net/zzh516451964zzh/article/details/127758080