当前位置: 首页 > article >正文

编写高质量Python (第28条) 控制推导逻辑的字表达式不要超过两个

第 28 条 控制推导逻辑的字表达式不要超过两个

​ 除了最基本的用法(参见 第 27 条)外,列表推导还支持多层循环。例如,要把矩阵转化为普通的一维列表,那么可以在推导时,使用两条 for 字表达式。这些子表达式会按照从左到右的顺序解读。

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [x for row in matrix for x in row]
print(flat)

>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]

​ 这样写简单易懂,这也正是多层循环在列表推导之中的合理用法。多层循环还可以用来重制那种两层深的结构。例如,如果要根据二维矩阵中每个元素的平方值构建一个新的二维矩阵,那么可以采用下面这种写法。这看起来有点儿复杂,因为它把小的推导逻辑 [x ** 2 for x in row] 嵌到了大的推导逻辑里面,不过,这行语句总体上不难理解。

squared = [[x ** 2 for x in row] for row in matrix]
print(squared)

>>>
[[1, 4, 9], [16, 25, 36], [49, 64, 81]]

​ 如果推导过程中还要再加一层循环,那么语句就会变得很长,必须把它分成多行来写,例如下面是把一个三维矩阵转化为普通一维列表的代码

my_lists = [
    [[1, 2, 3], [4, 5, 6]]
]
flat = [x for sublist1 in my_lists
        for sublist2 in sublist1
        for x in sublist2]

​ 在这种情况下,采用列表推导来实现,其实并不会比传统的 for 循环节省多少代码。下面常见的 for 循环改写刚才的例子。这次我们通过级别不同的缩进表示每一层循环的深度,这要比刚才那种三层矩阵的列表推导更加清晰。

flat = []
for sublist1 in my_lists:
    for sublist2 in sublist1:
        flat.extend(sublist2)

​ 推导的时候,可以使用多种 if 条件。如果这些 if 条件出现在同一层循环内,那么它们的关系默认是 and 关系,也就是必须同时成立。例如,如果要用原列表中大于 4 且是偶数的值来构建新列表,那么既可以连用两个 if,也可以只用一个 if,下面两种写法效果相同。

a = list(range(1, 11))
b = [x for x in a if x > 4 if x % 2 == 0]
c = [x for x in a if x > 4 and x % 2 == 0]
	在推导时,每一层的 for 字表达式都可以带有 if 语句。例如,要根据原矩阵构建新矩阵,把其中各元素之和大于等于 10 的那些行选出来,而且只保留其中能够被 3 整除的那些元素。这个逻辑用列表推导来写,并不需要太多的代码,但是这些代码理解起来会很困难。
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
filtered = [[x for x in row if x % 3 == 0]
            for row in matrix if sum(row) >= 10]

​ 这里建议大家不要用刚才的写法来推导新的 list、dict 或 set,因为这样写出来的代码很难让初次阅读这段程序的人看懂。对于 dict 来说,问题尤为严重。因为必须得把键与值的推导逻辑都表达出来。

​ 总之,在表示推导逻辑时,最多只应该写两个字表达式(例如两个 if 条件、两个 for 循环,或者一个 if 条件与一个 for 循环)。只要实现的比这还复杂,那就应该采用普通的 if 与 for 实现,并且可以考虑编写辅助函数(参见 第30条)。


http://www.kler.cn/a/158105.html

相关文章:

  • 【Linux】echo命令使用
  • Java——》JSONObjet 数据顺序
  • Upload-Labs-Linux
  • 工程化使用React
  • 前端知识笔记(二十一)———浏览器的缓存策略
  • 加强网站稳定性!学习如何进行高效压力测试!
  • 【矩阵论】Chapter 6—矩阵分解知识点总结复习(附Python实现)
  • 微机原理——定时器8253(8254)学习2应用与设计
  • RAG落地实践、AI游戏开发、上海·深圳·广州线下工坊启动!星河社区重磅周
  • 企业微信HOOK开发接口调用,发送语音消息
  • 如何在Linux环境搭建本地SVN服务器并结合cpolar实现公网访问
  • 协议栈的内部结构
  • jQuery选择器、操作DOM、事件处理机制、动画、ADJX操作知识点梳理
  • 数实融合!低代码推动工业数字化转型走“深”向“实”
  • Python爬虫技术:如何利用ip地址爬取动态网页
  • 梯度上升和随机梯度上升
  • 如何删除mac苹果电脑上面的流氓软件?
  • 【工作生活】汽车电子嵌入式开发简介
  • Stable diffusion ai图像生成本地部署教程
  • 蓝桥杯 动态规划