python进阶-推导式

推导式(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))
相关推荐
njidf2 小时前
C++中的访问者模式
开发语言·c++·算法
☆5662 小时前
如何为开源Python项目做贡献?
jvm·数据库·python
英俊潇洒美少年2 小时前
js 同步异步,宏任务微任务的关系
开发语言·javascript·ecmascript
C_Si沉思2 小时前
C++中的工厂模式变体
开发语言·c++·算法
m0_560396472 小时前
使用Python进行PDF文件的处理与操作
jvm·数据库·python
SEO-狼术2 小时前
Improve Navigation with In-Cell Hyperlinks
python·pdf
2301_816651222 小时前
用Python监控系统日志并发送警报
jvm·数据库·python
不会聊天真君6472 小时前
基础语法·中(golang笔记第二期)
开发语言·笔记·golang