推导式(Comprehension)是 Python 中一种简洁、高效创建数据结构 的语法糖。它把「循环 + 条件判断 + 元素处理」浓缩成一行代码,比传统的 for 循环更简洁,执行效率也更高。
Python 支持四种推导式:
- 列表推导式(List Comprehension) - 生成列表
- 字典推导式(Dict Comprehension) - 生成字典
- 集合推导式(Set Comprehension) - 生成集合(自动去重)
- 元组推导式(Tuple Comprehension) - 实际生成生成器,需要转换为元组
一、列表推导式
1.1 基本语法
# 基础格式
new_list = [expression for item in iterable]
# 带条件过滤
new_list = [expression for item in iterable if condition]
语法组成:
expression- 对每个元素的处理逻辑item- 遍历时的临时变量iterable- 可迭代对象(列表、字符串、range 等)condition- 可选的过滤条件
1.2 基础示例
示例 1:生成平方数列表
# 传统 for 循环
squares = []
for i in range(1, 6):
squares.append(i * i)
print(squares) # [1, 4, 9, 16, 25]
# 列表推导式(一行搞定)
squares = [i * i for i in range(1, 6)]
print(squares) # [1, 4, 9, 16, 25]
示例 2:字符串转大写
words = ['hello', 'world', 'python']
upper_words = [word.upper() for word in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
1.3 带条件过滤
# 筛选偶数并计算平方
even_squares = [i * i for i in range(1, 11) if i % 2 == 0]
print(even_squares) # [4, 16, 36, 64, 100]
# 筛选长度大于 3 的单词
words = ['cat', 'elephant', 'dog', 'tiger']
long_words = [w for w in words if len(w) > 3]
print(long_words) # ['elephant', 'tiger']
1.4 嵌套列表推导式
# 展平二维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 生成九九乘法表
table = [[f'{i}x{j}={i*j}' for j in range(1, 10)] for i in range(1, 10)]
二、字典推导式
2.1 基本语法
# 基础格式
new_dict = {key_expr: value_expr for item in iterable}
# 带条件过滤
new_dict = {key_expr: value_expr for item in iterable if condition}
2.2 基础示例
示例 1:生成数字与平方的映射
# 字典推导式
square_dict = {i: i**2 for i in range(1, 6)}
print(square_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 等价的传统写法
square_dict = {}
for i in range(1, 6):
square_dict[i] = i**2
示例 2:反转字典键值
original = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {v: k for k, v in original.items()}
print(reversed_dict) # {1: 'a', 2: 'b', 3: 'c'}
2.3 带条件过滤
# 筛选值大于 50 的项
scores = {'Alice': 85, 'Bob': 45, 'Charlie': 92, 'David': 38}
passed = {k: v for k, v in scores.items() if v >= 50}
print(passed) # {'Alice': 85, 'Charlie': 92}
# 筛选键长度为 3 的项
data = {'cat': 1, 'elephant': 2, 'dog': 3, 'ant': 4}
short_keys = {k: v for k, v in data.items() if len(k) == 3}
print(short_keys) # {'cat': 1, 'dog': 3, 'ant': 4}
2.4 实用场景
从两个列表创建字典:
keys = ['name', 'age', 'city']
values = ['Alice', 25, 'New York']
user_dict = {k: v for k, v in zip(keys, values)}
print(user_dict) # {'name': 'Alice', 'age': 25, 'city': 'New York'}
字典值转换:
prices = {'apple': '10', 'banana': '5', 'orange': '8'}
prices_int = {k: int(v) for k, v in prices.items()}
print(prices_int) # {'apple': 10, 'banana': 5, 'orange': 8}
三、集合推导式
3.1 基本语法
# 基础格式(使用花括号,但只有值没有键值对)
new_set = {expression for item in iterable}
# 带条件过滤
new_set = {expression for item in iterable if condition}
集合特性: 自动去重,无序存储。
3.2 基础示例
示例 1:自动去重
# 列表有重复元素
numbers = [1, 2, 2, 3, 4, 4, 5]
unique_squares = {x**2 for x in numbers}
print(unique_squares) # {1, 4, 9, 16, 25}(自动去重)
示例 2:提取唯一字符
text = 'hello world'
unique_chars = {char for char in text if char != ' '}
print(unique_chars) # {'h', 'e', 'l', 'o', 'w', 'r', 'd'}
3.3 带条件过滤
# 获取所有偶数的平方(去重)
numbers = [1, 2, 2, 3, 4, 4, 5, 6, 6]
even_squares = {x**2 for x in numbers if x % 2 == 0}
print(even_squares) # {4, 16, 36}
# 提取单词首字母(大写且去重)
words = ['apple', 'banana', 'avocado', 'cherry']
first_letters = {w[0].upper() for w in words}
print(first_letters) # {'A', 'B', 'C'}
3.4 实用场景
# 快速找出两个列表的交集
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
intersection = {x for x in list1 if x in list2}
print(intersection) # {4, 5}
四、元组推导式
⚠️ Python 没有真正的元组推导式 。使用圆括号的推导式语法会生成一个生成器对象(Generator),而不是元组。如果需要元组,必须显式转换。
4.2 语法对比
# 这不是元组推导式,而是生成器表达式
gen = (i**2 for i in range(1, 6))
print(gen) # <generator object <genexpr> at 0x...>
print(type(gen)) # <class 'generator'>
# 需要显式转换为元组
my_tuple = tuple(i**2 for i in range(1, 6))
print(my_tuple) # (1, 4, 9, 16, 25)
print(type(my_tuple)) # <class 'tuple'>
4.3 生成器表达式的优势
生成器表达式是惰性求值的,只在需要时才计算下一个值,节省内存。适合处理大数据集。
# 生成器:惰性求值,省内存
gen = (i**2 for i in range(1000000))
print(next(gen)) # 1(只计算第一个值)
print(next(gen)) # 4(计算第二个值)
# 列表推导式:立即计算所有值,占用内存
list_comp = [i**2 for i in range(1000000)] # 立即生成 100 万个元素
4.4 实用示例
# 示例 1:转换为元组
coordinates = tuple((x, x**2) for x in range(1, 4))
print(coordinates) # ((1, 1), (2, 4), (3, 9))
# 示例 2:配合 sum() 等函数使用生成器
total = sum(i**2 for i in range(1, 101)) # 无需转元组,直接使用生成器
print(total) # 338350
五、性能对比与最佳实践
5.1 推导式 vs 传统循环
import time
# 测试数据规模
n = 1000000
# 传统 for 循环
start = time.time()
result = []
for i in range(n):
result.append(i**2)
print(f'传统循环耗时: {time.time() - start:.4f}秒')
# 列表推导式
start = time.time()
result = [i**2 for i in range(n)]
print(f'列表推导式耗时: {time.time() - start:.4f}秒')
# 结论:列表推导式通常快 20-30%
5.2 最佳实践
✅ 简单逻辑用推导式 - 一行能表达清楚时优先使用
✅ 复杂逻辑用循环 - 多重嵌套或复杂判断时,传统循环更易读
✅ 大数据用生成器 - 处理大数据集时,生成器表达式更省内存
✅ 去重用集合推导式 - 需要去重时,集合推导式是最佳选择
✅ 键值映射用字典推导式 - 创建映射关系时首选字典推导式
5.3 可读性原则
# ❌ 不推荐:过度嵌套,难以理解
result = [[y**2 for y in row if y > 0] for row in matrix if sum(row) > 10]
# ✅ 推荐:拆分为多步,清晰易读
filtered_matrix = [row for row in matrix if sum(row) > 10]
result = [[y**2 for y in row if y > 0] for row in filtered_matrix]
六、四种推导式对比总结
|-----------|--------------------|-------------|----------------|
| 推导式类型 | 语法 | 返回类型 | 特点 |
| 列表推导式 | [x for x in ...] | list | 有序、可重复 |
| 字典推导式 | {k: v for ...} | dict | 键值对、键唯一 |
| 集合推导式 | {x for x in ...} | set | 无序、自动去重 |
| 元组推导式 | (x for x in ...) | generator | 需 tuple() 转换 |
七、实战案例
7.1 数据清洗
# 清洗用户输入数据:去除空格、转小写、过滤空值
user_inputs = [' Hello ', '', 'WORLD', ' Python ', '']
cleaned = [s.strip().lower() for s in user_inputs if s.strip()]
print(cleaned) # ['hello', 'world', 'python']
7.2 数据转换
# CSV 字符串转字典列表
csv_data = [
'name,age,city',
'Alice,25,New York',
'Bob,30,San Francisco'
]
headers = csv_data[0].split(',')
data = [dict(zip(headers, row.split(','))) for row in csv_data[1:]]
print(data)
# [{'name': 'Alice', 'age': '25', 'city': 'New York'},
# {'name': 'Bob', 'age': '30', 'city': 'San Francisco'}]
7.3 数据分组
# 按长度分组单词
words = ['cat', 'elephant', 'dog', 'tiger', 'ant']
grouped = {length: [w for w in words if len(w) == length]
for length in {len(w) for w in words}}
print(grouped)
# {3: ['cat', 'dog', 'ant'], 5: ['tiger'], 8: ['elephant']}
7.4 消息对象转字典
# 实际开发场景:把消息对象列表转为字典列表
# 假设有 message_to_dict 函数
new_messages = [message_to_dict(msg) for msg in all_messages]
# 等价于传统写法
new_messages = []
for msg in all_messages:
new_messages.append(message_to_dict(msg))