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)
Back to Blog

相关文章

阅读更多 »