推导式是 Python 独有的语法糖,能用一行代码代替好几行循环。
很多初学者看到{n for n in nums if n%2==0}这样的代码一脸懵。
这篇文章用一个例子讲透四种推导式,看完你也能写出优雅的 Python 代码。
📘 本期速览
- 四种推导式对比一览
- 列表推导式(最常用)
- 集合推导式(自动去重)
- 字典推导式(键值对)
- 生成器表达式(省内存)
- 性能对比与选择建议
一、四种推导式对比一览
以同一个数据为例:
nums={1,2,3,4,5,6}# 原始数据| 类型 | 代码 | 输出 | 符号 |
|---|---|---|---|
| 列表推导式 | [n for n in nums if n%2==0] | [2, 4, 6] | [] |
| 集合推导式 | {n for n in nums if n%2==0} | {2, 4, 6} | {} |
| 字典推导式 | {n: n**2 for n in nums if n%2==0} | {2:4, 4:16, 6:36} | {k:v} |
| 生成器表达式 | (n for n in nums if n%2==0) | <generator object> | () |
💡 记住这个规律:
[]得列表,{}得集合,{k:v}得字典,()得生成器
二、列表推导式 ——[]
最常用的推导式,输出一个列表。
基础用法
nums={1,2,3,4,5,6}# 筛选偶数result=[nforninnumsifn%2==0]print(result)# [2, 4, 6]带 else 的条件
# if-else 需要写在 for 前面tags=["偶数"ifn%2==0else"奇数"forninnums]print(tags)# ['奇数', '偶数', '奇数', '偶数', '奇数', '偶数']对元素进行运算
# 计算平方squared=[n**2forninnums]print(squared)# [1, 4, 9, 16, 25, 36]等价于传统写法
# 上面的代码等价于:result=[]forninnums:ifn%2==0:result.append(n)print(result)# [2, 4, 6]✅ 列表推导式能让代码更简洁、更 Pythonic。
三、集合推导式 ——{}
输出一个集合,特点是自动去重、无序。
基础用法
nums={1,2,3,4,5,6}# 筛选偶数result={nforninnumsifn%2==0}print(result)# {2, 4, 6}自动去重
# 原数据有重复时,集合会自动去重data=[1,2,2,3,4,4,5,6,6]unique_evens={nfornindataifn%2==0}print(unique_evens)# {2, 4, 6}⚠️ 注意:空集合不能写成
{}(那是空字典),必须用set()。
四、字典推导式 ——{k: v}
输出一个字典,需要同时指定键和值。
基础用法
nums={1,2,3,4,5,6}# 键=原数,值=平方result={n:n**2forninnumsifn%2==0}print(result)# {2: 4, 4: 16, 6: 36}键值判断
# 键=原数,值=奇偶性parity={n:("偶数"ifn%2==0else"奇数")forninnums}print(parity)# {1: '奇数', 2: '偶数', 3: '奇数', 4: '偶数', 5: '奇数', 6: '偶数'}交换字典的键和值
original={"a":1,"b":2,"c":3}swapped={v:kfork,vinoriginal.items()}print(swapped)# {1: 'a', 2: 'b', 3: 'c'}💡 字典推导式特别适合做数据转换和键值互换。
五、生成器表达式 ——()
输出一个生成器对象,特点是惰性求值、省内存。
基础用法
nums={1,2,3,4,5,6}# 创建生成器(注意是圆括号)gen=(nforninnumsifn%2==0)print(gen)# <generator object <genexpr> at 0x...>三种取值方式
# 方式1:转换为列表(一次性取完)gen=(nforninnumsifn%2==0)print(list(gen))# [2, 4, 6]# 方式2:用 for 循环遍历gen=(nforninnumsifn%2==0)forvalingen:print(val)# 2 \n 4 \n 6# 方式3:用 next() 逐个取值gen=(nforninnumsifn%2==0)print(next(gen))# 2print(next(gen))# 4print(next(gen))# 6# print(next(gen)) # StopIteration 错误⚠️ 生成器只能遍历一次,取完就没有了。
六、性能与内存对比
importsys nums=range(1,1000001)# 100万个数字# 列表推导式:立即生成全部结果,占用大量内存lst=[nforninnumsifn%2==0]print(f"列表占用:{sys.getsizeof(lst)}字节")# 约 8MB# 生成器表达式:几乎不占内存gen=(nforninnumsifn%2==0)print(f"生成器占用:{sys.getsizeof(gen)}字节")# 约 112 字节| 类型 | 内存占用 | 适用场景 |
|---|---|---|
| 列表推导式 | 大 | 数据量小、需要多次使用 |
| 集合/字典推导式 | 中等 | 需要去重或键值对 |
| 生成器表达式 | 极小 | 数据量大、只遍历一次 |
七、选择建议速查表
| 你的需求 | 推荐使用 |
|---|---|
| 需要索引或顺序 | 列表推导式[] |
| 需要去重 | 集合推导式{} |
| 需要键值对 | 字典推导式{k:v} |
| 数据量大 + 只遍历一次 | 生成器表达式() |
| 需要多次使用结果 | 列表/集合/字典推导式 |
八、避坑提醒
⚠️常见错误1:空集合用
{}wrong={}# 这是空字典,不是空集合!correct=set()# 这才是空集合
⚠️常见错误2:if-else 位置写错
# 筛选条件(没有 else)→ if 写在后面[nforninnumsifn>0]# 条件表达式(有 else)→ if-else 写在前面[nifn>0else0forninnums]
⚠️常见错误3:生成器被多次遍历
gen=(nfornin[1,2,3])print(list(gen))# [1,2,3]print(list(gen))# [] 已经消耗完了!
九、一句话总结
[]得列表,{}得集合,{k:v}得字典,()得生成器
把这四种推导式记牢,你的 Python 代码会变得更加简洁、优雅、高效。
📚 延伸阅读
如果你想继续深入,可以看:
- 嵌套推导式(多层循环)
- 推导式中的条件过滤进阶
- 生成器与迭代器的底层原理
如果觉得有用,欢迎点赞、收藏、转发给朋友。