列表推导式,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]

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

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

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

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

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

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

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

紧接着,再一起来看看这个例子,我们想把原始列表中大于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]

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

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]

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

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

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

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

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

matrix2d = [[j for i in range(3)] for j in range(3)]
# [[0, 0, 0], [1, 1, 1], [2, 2, 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]]
#     ]

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

# D1 = ['A', 'B']
# D2 = ['a', 'b']
# Dp = [('A', 1), ('A', 2), ('A', 3), ('B', 1), ('B', 2), ('B', 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')]

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

my_str = 'Hello, World!'
vowels = {i for i in my_str if i.lower() in 'aeiou'} # {'e', 'o'}
type(vowels) # <class 'set'>

打印类型也显示为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) # <class 'dict'>

当然,大胆发挥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}

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

data = (i for i in range(6))
type(data) # <class 'generator'>

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啥都生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值