Python 结构视角:列表推导式及其隐藏的复杂性
发布: (2025年12月14日 GMT+8 12:07)
5 min read
原文: Dev.to
Source: Dev.to
介绍
Timothy 在重构一些数据处理代码时,遇到了一个他看不懂的推导式。
“Margaret,有人写了这个推导式,我弄不清它到底在做什么。它全写在一行上,我的大脑直接……卡住了。”
Margaret 看了看代码:
result = [item for sublist in data for item in sublist if item > 0 if item % 2 == 0]
“啊,” Margaret 说,“这已经是从巧妙跨到令人困惑的推导式了。让我给你展示一下它到底是怎么工作的。”
问题:推导式走向错误
“推导式很强大,” Margaret 解释道,“但它们也可能变成只能写不能读的代码。当你嵌套循环并堆叠过滤条件时,执行顺序往往不是大多数人所期待的。”
Timothy 点点头。“我以为推导式是用来让代码更易读的。结果恰恰相反。”
基础推导式
numbers = [1, 2, 3, 4, 5]
squares = [n * n for n in numbers]
英文视图
将 numbers 设为 [1, 2, 3, 4, 5]。
将 squares 设为:
列表推导式:n * n
对于 numbers 中的每个 n
“这很清晰,” Margaret 说。“你正在通过对每个数字求平方来创建一个新列表。”
添加过滤条件
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_squares = [n * n for n in numbers if n % 2 == 0]
英文视图
将 numbers 设为 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]。
将 even_squares 设为:
列表推导式:n * n
对于 numbers 中的每个 n
如果 n % 2 == 0
结果:
[4, 16, 36, 64, 100]
多个过滤条件
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = [n for n in numbers if n > 3 if n % 2 == 0]
英文视图
将 numbers 设为 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]。
将 result 设为:
列表推导式:n
对于 numbers 中的每个 n
如果 n > 3
如果 n % 2 == 0
“连续两个
if是表示 OR 还是 AND?”
两个 if 子句会使用 AND 逻辑组合,等价于 if n > 3 and n % 2 == 0。
结果:
[4, 6, 8, 10]
嵌套循环
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [item for row in matrix for item in row]
英文视图
将 matrix 设为 [[1, 2, 3], [4, 5, 6], [7, 8, 9]]。
将 flat 设为:
列表推导式:item
对于 matrix 中的每个 row
对于 row 中的每个 item
等价循环:
flat = []
for row in matrix:
for item in row:
flat.append(item)
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
结合嵌套循环和过滤条件
data = [[1, -2, 3], [4, -5, 6], [7, 8, -9]]
result = [item for sublist in data for item in sublist if item > 0 if item % 2 == 0]
英文视图
将 data 设为 [[1, -2, 3], [4, -5, 6], [7, 8, -9]]。
将 result 设为:
列表推导式:item
对于 data 中的每个 sublist
对于 sublist 中的每个 item
如果 item > 0
如果 item % 2 == 0
展开后的版本:
result = []
for sublist in data: # 第一个 for
for item in sublist: # 第二个 for
if item > 0: # 第一个 if
if item % 2 == 0: # 第二个 if
result.append(item)
结果:
[4, 6, 8]
当推导式变得过于复杂时
指南
在以下情况下使用推导式:
- 逻辑能够舒适地写在一行内
- 转换过程简单且显而易见
- 嵌套层级最多只有一层
- 过滤条件直接明了
在以下情况下避免使用推导式:
- 需要带有复杂条件的嵌套循环
- 逻辑需要多个步骤才能完成
- 大声朗读时仍然让人摸不着头脑
- 你想要添加注释来解释它
更易读的重写示例:
# 更易读的版本
result = []
for sublist in data:
for item in sublist:
if item > 0 and item % 2 == 0:
result.append(item)