对于习惯了 Java 严谨语法的后端开发者来说,刚接触 Python 时总会不自觉地用 Java 的思维写代码:创建集合先初始化、循环遍历、逐个 add 元素,再加上各种条件判断,几行甚至十几行代码才能完成一个简单列表构造。
而在 Python 里,有一个能让代码瞬间优雅起来的语法 —— 推导式。它不仅精简代码,还自带底层性能优化,是从 Java 转 Python 必须掌握的 “Pythonic” 核心写法。
这篇文章就从 Java 开发者熟悉的角度,带你彻底搞懂列表推导式、字典推导式,对比写法、看清差异,上手即用。
一、什么是推导式
推导式是 Python 内置的一种快速创建序列的语法,可以在一行内完成:遍历 → 计算 / 处理 → 条件过滤 → 生成新容器。
对应到 Java 里,就相当于把 “新建集合 + for 循环 + if 判断 + add/put” 压缩成一句表达式,可读性更强、运行效率更高。
Python 常用推导式主要有:
- 列表推导式:快速生成 list
- 字典推导式:快速生成 dict
- 集合推导式:快速生成带自动去重的 set
二、列表推导式
1. 基本语法
[表达式 for 变量 in 可迭代对象]
它等价于:
result = []
for 变量 in 可迭代对象:
result.append(表达式)
Java 对比示例
Java 写法
List<Integer> cubeList = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
cubeList.add(i * i * i);
}
// 输出:[1, 8, 27, 64, 125, 216]
Python 列表推导式
cube_list = [i ** 3 for i in range(1, 7)]
# 输出:[1, 8, 27, 64, 125, 216]
一行搞定,结构清晰、代码极简,无需手动初始化列表和调用 append 方法。
2. 带条件过滤的推导式
在循环后面加上 if 条件,就能快速实现数据筛选,无需额外嵌套 if 代码块。
Java 写法
List<Integer> evenList = new ArrayList<>();
for (int i = 1; i <= 12; i++) {
if (i % 3 == 0) {
evenList.add(i);
}
}
Python 推导式
even_list = [i for i in range(1, 13) if i % 3 == 0]
# 输出:[3, 6, 9, 12]
3. 嵌套循环推导式
面对双层循环场景,推导式也能轻松压缩成一行,避免多层嵌套的冗余代码。
Java 双层循环
List<String> pairList = new ArrayList<>();
int[] nums = {1, 2};
char[] chars = {'a', 'b', 'c'};
for (int num : nums) {
for (char c : chars) {
pairList.add(num + "" + c);
}
}
Python 嵌套推导式
pair_list = [str(num) + char for num in [1,2] for char in ['a','b','c']]
# 输出:['1a', '1b', '1c', '2a', '2b', '2c']
三、字典推导式
字典推导式用来快速构建键值对结构,对标 Java 中的 HashMap,无需手动初始化 Map 和调用 put 方法,一行就能完成字典创建。
基本语法
{键表达式: 值表达式 for 变量 in 可迭代对象}
Java 对比示例
Java 写法
Map<Integer, Integer> squareMap = new HashMap<>();
for (int i = 1; i <= 5; i++) {
squareMap.put(i, i * i);
}
Python 字典推导式
square_map = {i: i * i for i in range(1, 6)}
# 输出:{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
带条件过滤的字典推导
结合条件判断,可快速筛选出符合要求的键值对,比如筛选出成绩合格的学生:
score_map = {
"小明": 72,
"小红": 93,
"小刚": 59,
"小丽": 88
}
passed = {name: score for name, score in score_map.items() if score >= 60}
# 输出:{'小明': 72, '小红': 93, '小丽': 88}
反转字典键值
无需额外循环遍历,一行推导式就能实现字典键值反转,比 Java 手动遍历反转更高效:
original = {"name": "age", "height": "weight"}
reversed_dict = {v: k for k, v in original.items()}
# 输出:{'age': 'name', 'weight': 'height'}
四、集合推导式(自动去重)
集合推导式语法和列表推导式类似,只是用 {} 包裹,最大特点是自动去重,无需像 Java 那样手动判断去重或借助 HashSet。
num_list = [1, 2, 2, 3, 3, 3, 4, 4]
unique_set = {num for num in num_list}
# 输出:{1, 2, 3, 4}
在 Java 里要实现类似效果,要么手动遍历判断去重,要么新建 HashSet 传入列表,而 Python 一行就能搞定,简洁又高效。
五、为什么 Java 程序员要学推导式
- 代码更简洁:多行循环代码压缩为一行表达式,逻辑更紧凑,减少模板化代码冗余。
- 性能更好:推导式由 Python 解释器底层优化,比循环里反复调用 append/put 方法更快,减少函数调用开销。
- 更符合 Python 风格:专业的 Python 代码中大量使用推导式,学会它才算真正入门 Python,摆脱 “Java 风格” 的 Python 代码。
- 降低思维负担:处理列表、字典的简单遍历、过滤场景,无需再编写固定的循环模板,专注核心逻辑。
六、使用注意事项
- 不要过度嵌套:两层循环以内的场景使用推导式合适,三层及以上嵌套会严重影响代码可读性,不如拆成普通循环。
- 大数据量慎用列表推导式:列表推导式会一次性生成所有数据并占用内存,若数据量极大,可改用生成器(用 () 包裹)实现惰性计算,节省内存。
- 逻辑复杂时别硬挤:可读性永远比 “一行写完” 更重要,若逻辑包含多个判断、复杂计算,建议拆分为普通循环,便于后续维护。
七、总结(Java 开发者速记)
- 列表推导式:
[exp for x in iter if cond]→ 对应 Java List + 循环 + add - 字典推导式:
{k:v for x in iter if cond}→ 对应 Java HashMap + 循环 + put - 集合推导式:
{exp for x in iter}→ 自动去重,对应 Java HashSet
学会推导式,你的 Python 代码会立刻从 “Java 风格” 升级为 “地道 Python 风格”,简洁、高效、易维护。
如果你也是从 Java 转向 Python,不妨从推导式开始,一点点体会 Python 的优雅与强大,解锁更高效的编程方式。