
摘要本文系统讲解 Python 列表推导式的核心用法从基本语法、条件筛选、if-else 双分支、嵌套循环到字典推导式和集合推导式并结合生成器表达式与海象运算符等进阶技巧最后通过实战案例和总结表格帮助读者快速掌握这一简洁高效的编程范式。一、为什么要学列表推导式先看一段代码这是大多数初学者写的# 需求生成 1 到 10 的平方列表 squares [] for i in range(1, 11): squares.append(i * i) print(squares) # 输出[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]功能没问题但用了 3 行。而 Python 老手写同样的功能只需要 1 行squares [i * i for i in range(1, 11)] print(squares) # 输出[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]这就是列表推导式List Comprehension。它不是什么高级黑科技而是 Python 提供的一种简洁语法让你用一行代码完成 创建列表 循环 追加 的操作。学会它有三个好处代码更短3 行变 1 行可读性反而更高执行更快列表推导式在 CPython 里是专门的字节码实现少了append的属性查找和方法调用开销通常比等价的 for append 略快面试必考几乎所有 Python 面试都会问import timeit # 同样的任务两种写法对比 for_loop squares [] for i in range(1000): squares.append(i * i) comprehension squares [i * i for i in range(1000)] n 10000 t1 timeit.timeit(for_loop, numbern) t2 timeit.timeit(comprehension, numbern) print(ffor 循环: {t1:.4f}s) print(f列表推导式: {t2:.4f}s) print(f快了: {(t1 - t2) / t1 * 100:.1f}%)补充这个快了多少没有一个固定数字它取决于循环体多复杂、列表多大、Python 版本。我在自己的机器上Python 3.13跑上面这段大致在 20%-40% 之间浮动。但这个差距在绝大多数业务代码里根本不值得优化——你的瓶颈几乎永远不会是这里。用列表推导式的真正理由是可读性不是性能。性能只是附带的赠品。二、基本语法列表推导式的标准格式[表达式 for 变量 in 可迭代对象]拆解一下表达式你想对每个元素做什么操作变量循环中的临时变量可迭代对象列表、range、字符串、字典等示例 1把字符串的每个字符变成大写chars [c.upper() for c in hello] print(chars) # 输出[H, E, L, L, O]示例 2生成 0 到 9 的数字列表nums [x for x in range(10)] print(nums) # 输出[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]三、带条件筛选的列表推导式这是最常用的场景。语法如下[表达式 for 变量 in 可迭代对象 if 条件]只有满足if条件的元素才会被放入新列表。示例 1筛选出 1 到 20 中的偶数evens [x for x in range(1, 21) if x % 2 0] print(evens) # 输出[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]对比普通写法evens [] for x in range(1, 21): if x % 2 0: evens.append(x)一目了然列表推导式简洁太多。示例 2筛选出列表中长度大于 3 的字符串words [apple, hi, banana, ok, orange] long_words [w for w in words if len(w) 3] print(long_words) # 输出[apple, banana, orange]四、if-else 双分支的列表推导式注意如果需要if-else双分支不是筛选而是根据条件返回不同值语法位置会变[表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]示例把大于 5 的数变成 大否则变成 小nums [1, 7, 3, 9, 2, 6] result [大 if x 5 else 小 for x in nums] print(result) # 输出[小, 大, 小, 大, 小, 大]常见错误把 if-else 写在 for 后面# 错误写法语法报错 result [大 for x in nums if x 5 else 小] # 错误 # 正确写法 result [大 if x 5 else 小 for x in nums] # 正确记住一个口诀单条件筛选写后面双分支判断写前面。五、嵌套循环的列表推导式列表推导式还支持嵌套循环语法是按从外到内的顺序写[表达式 for 变量1 in 可迭代对象1 for 变量2 in 可迭代对象2]示例生成两个列表的所有组合colors [红, 蓝] sizes [S, M, L] combinations [(c, s) for c in colors for s in sizes] print(combinations) # 输出[(红, S), (红, M), (红, L), (蓝, S), (蓝, M), (蓝, L)]等价于combinations [] for c in colors: for s in sizes: combinations.append((c, s))六、不止列表字典推导式和集合推导式学会了列表推导式另外两个几乎不用学语法一模一样只是把方括号换掉字典推导式用花括号 键值对# 生成一个数字到平方的映射 square_dict {x: x * x for x in range(1, 6)} print(square_dict) # 输出{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}集合推导式用花括号自动去重nums [1, 2, 2, 3, 3, 3, 4] unique_squares {x * x for x in nums} print(unique_squares) # 输出{1, 4, 9, 16}补充1生成器表达式把方括号换成圆括号# 方括号立即生成完整列表全部载入内存 squares_list [x * x for x in range(1000000)] # 内存占用约 40MB # 圆括号生成器惰性求值几乎不占内存 squares_gen (x * x for x in range(1000000)) # 内存占用约 100 字节只存生成规则不存数据什么时候必须用生成器# ❌ 危险1000 万条数据一次性进内存可能直接 OOM total sum([x * x for x in range(10000000)]) # ✅ 正确去掉方括号一个一个算内存恒定 total sum(x * x for x in range(10000000))注意sum(x * x for x in ...)这种写法——生成器作为函数参数时可以再省一层括号这是 Python 的经典惯用法。判断标准很简单数据量大、或者只需要遍历一次 → 用生成器圆括号需要反复访问、需要 len()、需要切片 → 用列表方括号补充2海象运算符# Python 3.8 海象运算符 : —— 避免重复计算 data [hello, hi, world] # ❌ len() 被调用了两次 lengths [len(s) for s in data if len(s) 3] # ✅ 用 : 把中间结果存下来只算一次 lengths [n for s in data if (n : len(s)) 3] print(lengths) # [5, 5]这个技巧在筛选条件依赖某个耗时计算结果时特别有用比如正则匹配# 传统写法要匹配两次 results [m.group(1) for s in lines if (m : pattern.match(s))]七、什么时候不该用列表推导式列表推导式虽好但不是万能的。以下情况建议用普通 for 循环1. 逻辑太复杂超过 2 个条件# ⚠️ 这种写法语法没问题多个 if 等价于 and但嵌套深了可读性会断崖式下跌 result [ transform(x) for row in matrix for item in row for x in item if x is not None if validate(x) ] # 三层循环 两个条件读到第三层你已经忘了第一层在干什么 换成普通循环逻辑立刻清晰 result [] for row in matrix: for item in row: for x in item: if x is not None and validate(x): result.append(transform(x))2. 循环体内有副作用打印、写文件、修改外部变量# 不建议列表推导式应该用来生成数据不是执行操作 [print(x) for x in range(10)] # 虽然能跑但语义不对 # 正确做法 for x in range(10): print(x)3. 列表推导式太长一行放不下如果表达式很长拆成多行反而不如普通循环清晰。记住可读性永远优先于炫技。八、实战案例统计文本中每个单词的长度sentence Python is a powerful programming language words sentence.split() # 普通写法 lengths [] for w in words: lengths.append(len(w)) # 列表推导式写法 lengths [len(w) for w in words] print(lengths) # 输出[6, 2, 1, 8, 11, 8]再进阶一点同时筛选出长度大于 3 的单词long_word_lengths [len(w) for w in words if len(w) 3] print(long_word_lengths) # 输出[6, 8, 11, 8]九、总结场景语法基本用法[表达式 for 变量 in 可迭代对象]条件筛选[表达式 for 变量 in 可迭代对象 if 条件]双分支判断[表达式1 if 条件 else 表达式2 for 变量 in 可迭代对象]嵌套循环[表达式 for 变量1 in 对象1 for 变量2 in 对象2]字典推导式{键: 值 for 变量 in 可迭代对象}集合推导式{表达式 for 变量 in 可迭代对象}记住三个原则单条件筛选写后面双分支判断写前面列表推导式用来生成数据不用来执行操作可读性优先复杂逻辑用普通 for 循环列表推导式是 Python 优雅性的典型代表多写几次就会形成肌肉记忆。建议把文中的例子自己敲一遍体会从 3 行循环 到 1 行推导式 的思维转变。