列表推导式是Python中最具特色的语法之一,它允许用简洁的一行代码生成复杂列表,替代传统循环结构,使代码更紧凑、高效。
一、列表推导式基础语法
标准结构模板
# 列表推导式基本语法
new_list = [expression for item in iterable]
# 等价于传统循环
new_list = []
for item in iterable:
new_list.append(expression)
基础应用示例
# 示例1:生成平方数列表
squares = [x ** 2 for x in range(10)] # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 示例2:字符串转大写
names = ["alice", "bob", "charlie"]
upper_names = [name.upper() for name in names] # ["ALICE", "BOB", "CHARLIE"]
# 示例3:从文件读取行并去除换行符
with open("data.txt") as f:
lines = [line.strip() for line in f]
二、带条件过滤的推导式
条件语法模板
# 带if条件的推导式
new_list = [expression for item in iterable if condition]
# 等价于
new_list = []
for item in iterable:
if condition:
new_list.append(expression)
条件应用示例
# 示例1:过滤偶数
numbers = [1, 2, 3, 4, 5, 6]
even_numbers = [x for x in numbers if x % 2 == 0] # [2, 4, 6]
# 示例2:筛选非空字符串
texts = ["hello", "", "world", None, "!"]
valid_texts = [t.strip() for t in texts if t and t.strip()] # ["hello", "world", "!"]
# 示例3:复杂条件组合
data = [10, -5, 0, 3, -8, 2]
filtered = [x * 2 for x in data if x > 0 and x % 2 == 0] # [20, 4]
三、嵌套循环推导式
嵌套语法模板
# 嵌套循环推导式
new_list = [expression for item1 in iterable1 for item2 in iterable2]
# 等价于
new_list = []
for item1 in iterable1:
for item2 in iterable2:
new_list.append(expression)
嵌套应用示例
# 示例1:矩阵转置
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose = [[row[i] for row in matrix] for i in range(3)] # [[1,4,7], [2,5,8], [3,6,9]]
# 示例2:笛卡尔积
colors = ["red", "blue"]
sizes = ["S", "M", "L"]
products = [f"{c}-{s}" for c in colors for s in sizes] # ["red-S", "red-M", ..., "blue-L"]
# 示例3:文件路径遍历
import os
image_files = [os.path.join(d, f) for d, _, fs in os.walk("images") for f in fs
if f.endswith((".jpg", ".png", ".jpeg"))]
四、推导式中的条件表达式
三元表达式应用
# 带三元表达式的推导式
new_list = [value_if_true if condition else value_if_false for item in iterable]
# 等价于
new_list = []
for item in iterable:
if condition:
new_list.append(value_if_true)
else:
new_list.append(value_if_false)
条件表达式示例
# 示例1:奇偶分类标记
numbers = [1, 2, 3, 4, 5]
flags = ["even" if x % 2 == 0 else "odd" for x in numbers] # ["odd", "even", "odd", "even", "odd"]
# 示例2:安全数据转换
data = ["10", "20", "abc", "30"]
converted = [int(x) if x.isdigit() else 0 for x in data] # [10, 20, 0, 30]
# 示例3:复杂逻辑处理
scores = [85, 92, 78, 65, 95]
grades = ["A" if s >= 90 else "B" if s >= 80 else "C" for s in scores] # ["B", "A", "B", "C", "A"]
五、列表推导式与传统方法对比
与map/filter函数对比
# 示例:计算平方(map更简洁)
numbers = [1, 2, 3, 4]
squares1 = [x**2 for x in numbers] # 列表推导式
squares2 = list(map(lambda x: x**2, numbers)) # map函数
# 示例:过滤偶数(列表推导式更直观)
even1 = [x for x in numbers if x % 2 == 0] # 列表推导式
even2 = list(filter(lambda x: x % 2 == 0, numbers)) # filter函数
# 示例:复合操作(列表推导式更灵活)
result1 = [x.upper() + "!" for x in names if len(x) > 3] # 推导式一站式处理
result2 = list(map(lambda x: x.upper() + "!", filter(lambda n: len(n) > 3, names))) # 函数式组合
性能对比测试
import time
# 测试数据
n = 1000000
numbers = list(range(n))
# 列表推导式
start = time.time()
squares = [x**2 for x in numbers]
end1 = time.time()
# 传统循环
start2 = time.time()
squares2 = []
for x in numbers:
squares2.append(x**2)
end2 = time.time()
print(f"推导式耗时: {end1 - start:.6f}秒")
print(f"传统循环耗时: {end2 - start2:.6f}秒")
# 输出:推导式通常比传统循环快10-15%
六、进阶技巧与注意事项
嵌套推导式优化
# 反模式:过度嵌套(难以阅读)
matrix = [[1,2],[3,4],[5,6]]
flattened = [x for row in matrix for x in row if x % 2 == 0] # 推荐写法
flattened_bad = [x for row in matrix if x % 2 == 0 for x in row] # 错误顺序,可读性差
生成器表达式(惰性求值)
# 列表推导式(立即生成全部元素)
list_gen = [x**2 for x in range(10**6)] # 占用大量内存
# 生成器表达式(按需生成)
gen_expr = (x**2 for x in range(10**6)) # 内存高效
first_ten = list(islice(gen_expr, 10)) # 仅获取前10个元素
避免过度使用
# 复杂逻辑应拆分为函数(反模式)
data = [1, -2, 3, -4, 5]
result = [math.sqrt(x) if x > 0 else None for x in data if x % 2 == 1]
# 优化写法
def process(x):
if x % 2 != 1:
return None
return math.sqrt(x) if x > 0 else None
result = [process(x) for x in data] # 更清晰的逻辑
七、综合应用案例
案例1:数据清洗与转换
# 原始数据(包含空值和异常格式)
raw_data = ["10.5", "20", "invalid", "30.0", "", "15"]
# 使用列表推导式清洗数据
cleaned = [float(x) for x in raw_data if x.strip() and x.replace(".", "", 1).isdigit()]
# 结果: [10.5, 20.0, 30.0, 15.0]
案例2:图像文件批量处理
import os
from PIL import Image
# 查找所有图像文件并调整尺寸
image_dir = "photos"
target_size = (800, 600)
# 列表推导式查找文件
image_files = [os.path.join(image_dir, f) for f in os.listdir(image_dir)
if f.lower().endswith((".jpg", ".png", ".jpeg"))]
# 处理图像(结合生成器表达式)
for img_path in (Image.open(f) for f in image_files):
img_path.resize(target_size).save(f"resized_{os.path.basename(img_path.filename)}")
案例3:多维数据处理
# 学生成绩数据
grades = [
["Alice", 85, 90, 78],
["Bob", 75, 82, 88],
["Charlie", 92, 87, 94]
]
# 计算平均分并生成报告
reports = [
f"{name}: 平均分 {sum(scores[1:])/len(scores[1:]):.2f}"
for name, *scores in grades
]
# 结果: ["Alice: 平均分 84.33", "Bob: 平均分 81.67", "Charlie: 平均分 91.00"]
八、总结:何时使用列表推导式
推荐使用场景:
1. 简单的数据转换(如类型转换、格式调整)
2. 单一条件的数据过滤
3. 二维数据的扁平化或重组
4. 不需要复杂逻辑的快速列表生成
不推荐使用场景:
1. 多层嵌套循环(超过2层)
2. 包含复杂条件判断(超过2个if条件)
3. 需要修改原始数据或有副作用的操作
4. 逻辑复杂到影响代码可读性
列表推导式是Python的"语法糖",合理使用可以显著简化代码,但过度追求简洁可能导致代码难以维护。最佳实践是:对于简单逻辑,用推导式提升效率;对于复杂逻辑,优先考虑可读性,通过函数封装实现功能。