Python推导式(Comprehensions)

在 Python 中,推导式(Comprehensions) 是一种简洁、高效地创建序列或映射对象的语法结构。你可以把它理解为:用一段描述性的表达式,直接生成一个完整的容器(列表、集合、字典) 。推导式让代码更紧凑、可读性更高,并且在大多数情况下执行速度比普通的 for 循环更快。

下面我们逐一详细解说三种标准推导式,并澄清"元组推导式"为何实际上是生成器。


1. 列表推导式(List Comprehension)

列表推导式是最常用的一种推导式,用于快速生成新的列表。

基本语法
python 复制代码
[expression for item in iterable if condition]
  • expression:对 item 的运算或直接就是 item 本身。
  • for item in iterable:迭代任何可迭代对象。
  • if condition(可选):筛选条件,只有条件为 Trueitem 才会被处理。
执行逻辑
  1. 遍历 iterable 中的每一个元素。
  2. 如果提供了 if,则先判断条件;条件为 False 则跳过。
  3. 对符合条件的元素计算 expression,将结果放入新列表。
示例
python 复制代码
# 生成 0~9 的平方列表
squares = [x**2 for x in range(10)]
print(squares)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# 带条件的:只保留偶数平方
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)  # [0, 4, 16, 36, 64]

# 嵌套循环:生成坐标对
coords = [(x, y) for x in range(2) for y in range(3)]
print(coords)  # [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]

# 对字符串列表处理
words = ["hello", "world", "python"]
upper_words = [w.upper() for w in words]
print(upper_words)  # ['HELLO', 'WORLD', 'PYTHON']
特点与优势
  • 速度快 :列表推导式在 C 语言层面进行循环和追加,避免了 Python 层的 append 方法调用开销。
  • 可读性强 :将意图集中在一行内,避免冗长的 for 循环结构。
  • 内存占用:会立即生成完整的列表对象,数据量大时需注意内存消耗。

2. 集合推导式(Set Comprehension)

集合推导式与列表推导式几乎相同,只是用花括号 {} 包裹,生成的是一个集合(set),因此自动去重且无序。

基本语法
python 复制代码
{expression for item in iterable if condition}
示例
python 复制代码
# 生成 0~9 的平方集合(自动去重)
squares_set = {x**2 for x in range(-3, 4)}  # 负数平方与正数相同
print(squares_set)  # {0, 1, 4, 9}

# 从列表中去重并转为大写
names = ["Alice", "bob", "alice", "Bob", "Charlie"]
unique_names = {name.capitalize() for name in names}
print(unique_names)  # {'Alice', 'Bob', 'Charlie'}

# 带条件的集合推导式
vowels = {char for char in "hello world" if char in "aeiou"}
print(vowels)  # {'e', 'o'}
特点
  • 自动去重:集合不允许重复元素。
  • 无序性:输出顺序不固定(但 Python 3.7+ 后字典和集合内部顺序是插入顺序,但集合顺序依然可能因哈希随机化而变化)。
  • 语法与列表推导式仅括号不同,但意义不同。

3. 字典推导式(Dictionary Comprehension)

字典推导式也使用花括号 {},但必须包含冒号 : 来区分键和值。

基本语法
python 复制代码
{key_expression: value_expression for item in iterable if condition}
示例
python 复制代码
# 生成数字及其平方的映射
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# 从两个列表构建字典
keys = ["name", "age", "city"]
values = ["Alice", 30, "New York"]
info = {k: v for k, v in zip(keys, values)}
print(info)  # {'name': 'Alice', 'age': 30, 'city': 'New York'}

# 带条件的字典推导式
numbers = [1, 2, 3, 4, 5, 6]
even_odd = {n: ("even" if n % 2 == 0 else "odd") for n in numbers}
print(even_odd)  # {1: 'odd', 2: 'even', 3: 'odd', 4: 'even', 5: 'odd', 6: 'even'}

# 交换字典的键和值
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
print(swapped)  # {1: 'a', 2: 'b', 3: 'c'}
特点
  • 键唯一性:如果表达式产生的键重复,后面的值会覆盖前面的值。
  • 非常适用于对现有字典进行过滤、转换或重组。

4. "元组推导式" ------ 实际上是生成器表达式

你可能会尝试用圆括号写类似推导式的东西:

python 复制代码
tup = (x**2 for x in range(5))
print(tup)  # <generator object <genexpr> at 0x...>

你会发现得到的不是元组 ,而是一个 generator 对象。这就是为什么 Python 里**没有"元组推导式"**的原因。

生成器表达式(Generator Expression)
  • 语法:(expression for item in iterable if condition)
  • 它返回一个生成器对象,该对象是惰性求值的:只在需要下一个元素时才计算,不一次性占用大量内存。
  • 可以把它当作一种"迭代器工厂",用于函数调用、for 循环或转换为其他容器。
示例
python 复制代码
# 生成器表达式
gen = (x**2 for x in range(5))
print(next(gen))  # 0
print(next(gen))  # 1
print(list(gen))  # [4, 9, 16] (剩余的元素)

# 常用场景:作为函数参数,避免中间列表
sum_of_squares = sum(x**2 for x in range(10))  # 没有额外的列表内存开销
如何得到一个元组?

如果你想要一个元组,可以将生成器表达式传给 tuple() 构造函数

python 复制代码
tup = tuple(x**2 for x in range(5))
print(tup)  # (0, 1, 4, 9, 16)

但这不是推导式语法,而是类型转换。


总结对比表

类型 语法 输出类型 特点
列表推导式 [exp for ...] list 有序、可重复、立即生成
集合推导式 {exp for ...} set 无序、去重、立即生成
字典推导式 {k: v for ...} dict 键值对、键唯一、立即生成
生成器表达式 (exp for ...) generator 惰性求值、内存友好、只能迭代一次

使用建议

  • 列表推导式:适用于结果集规模不大、需要随机访问或多次迭代的场景。
  • 集合推导式:需要去重且不关心顺序时使用。
  • 字典推导式:构建或转换映射关系时非常方便。
  • 生成器表达式:处理大规模数据流、或者只需要一次遍历时使用,可以有效节省内存。

推导式是 Python 风格的精华之一,合理使用能让代码更加 Pythonic

相关推荐
m0_716765232 小时前
数据结构三要素、时间复杂度计算详解
开发语言·数据结构·c++·经验分享·笔记·算法·visual studio
卷心菜狗2 小时前
Python进阶基础--面向对象编程(OOP)
开发语言·python
开心码农1号2 小时前
RabbitMQ 生产运维命令大全
linux·开发语言·ruby
网安INF2 小时前
数据结构第二章复习:线性表
java·开发语言·数据结构
superior tigre2 小时前
某为25.9.28 Yolo检测器中的anchor聚类(python实现)
python·yolo·聚类
aq55356002 小时前
Laravel10.X核心特性全解析
java·开发语言·spring boot·后端
这个人懒得名字都没写2 小时前
PyCharm图像查看器插件PixelLens
ide·python·pycharm
油墨香^_^2 小时前
Spring Boot集成WebSocket,实现后台向前端推送信息
开发语言