Python 教程 08:列表推导式入门
“简洁是智慧的灵魂。” —— 莎士比亚
列表推导式是 Python 最具特色的语法之一,它让你用一行代码完成原本需要多行循环才能实现的功能。这不仅是代码的简化,更是思维方式的提升。
1. 什么是列表推导式
列表推导式(List Comprehension)是一种简洁的创建列表的方式。
传统方法:
# 生成1-10的平方
squares = []
for i in range(1, 11):
squares.append(i ** 2)
print(squares) # [1, 4, 9, 16, ..., 100]
列表推导式:
# 一行搞定
squares = [i ** 2 for i in range(1, 11)]
print(squares) # [1, 4, 9, 16, ..., 100]
代码从 3 行变成 1 行,清晰简洁,这就是 Python 的魅力。
2. 基本语法
[表达式 for 变量 in 序列]
执行过程:
- 遍历序列中的每个元素
- 将元素赋值给变量
- 计算表达式
- 将结果添加到新列表
# 示例
numbers = [1, 2, 3, 4, 5]
# 每个数乘以2
doubled = [n * 2 for n in numbers]
print(doubled) # [2, 4, 6, 8, 10]
# 转换为字符串
str_list = [str(n) for n in numbers]
print(str_list) # ['1', '2', '3', '4', '5']
# 调用方法
names = ['alice', 'bob', 'charlie']
capitalized = [name.capitalize() for name in names]
print(capitalized) # ['Alice', 'Bob', 'Charlie']
3. 带条件的列表推导式
可以添加 if 条件进行过滤:
[表达式 for 变量 in 序列 if 条件]
# 筛选偶数
numbers = range(1, 11)
evens = [n for n in numbers if n % 2 == 0]
print(evens) # [2, 4, 6, 8, 10]
# 筛选并转换
words = ['apple', 'banana', 'cherry', 'date']
long_words = [w.upper() for w in words if len(w) > 5]
print(long_words) # ['BANANA', 'CHERRY']
# 过滤负数并求平方
nums = [-2, -1, 0, 1, 2, 3]
positive_squares = [n ** 2 for n in nums if n > 0]
print(positive_squares) # [1, 4, 9]
4. 带 if-else 的列表推导式
if-else 要放在 for 前面:
[表达式1 if 条件 else 表达式2 for 变量 in 序列]
# 奇数平方,偶数不变
numbers = range(1, 11)
result = [n ** 2 if n % 2 == 1 else n for n in numbers]
print(result) # [1, 2, 9, 4, 25, 6, 49, 8, 81, 10]
# 标记正负数
nums = [-2, -1, 0, 1, 2]
labels = ['负' if n < 0 else ('零' if n == 0 else '正') for n in nums]
print(labels) # ['负', '负', '零', '正', '正']
区别:
- 只有 if:过滤,生成的列表可能更短
- if-else:转换,生成的列表长度不变
5. 嵌套列表推导式
处理二维列表或嵌套结构:
# 二维列表展平
matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
# 方法1:先外层后内层
flat = [num for row in matrix for num in row]
print(flat) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 等价的传统写法
flat = []
for row in matrix:
for num in row:
flat.append(num)
# 生成九九乘法表
table = [f"{i}×{j}={i*j}" for i in range(1, 10) for j in range(1, i+1)]
print(table[:5]) # ['1×1=1', '2×1=2', '2×2=4', '3×1=3', '3×2=6']
6. 其他推导式
Python 还有字典推导式、集合推导式:
字典推导式
{键表达式: 值表达式 for 变量 in 序列}
# 创建字典
numbers = range(1, 6)
squares_dict = {n: n ** 2 for n in numbers}
print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 交换字典键值
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
# 筛选字典
scores = {'Alice': 85, 'Bob': 92, 'Charlie': 78, 'David': 95}
passed = {name: score for name, score in scores.items() if score >= 80}
print(passed) # {'Alice': 85, 'Bob': 92, 'David': 95}
集合推导式
{表达式 for 变量 in 序列}
# 去重并转换
numbers = [1, 1, 2, 2, 3, 3]
unique_squares = {n ** 2 for n in numbers}
print(unique_squares) # {1, 4, 9}
# 提取首字母
words = ['apple', 'banana', 'apricot', 'blueberry', 'cherry']
first_letters = {w[0] for w in words}
print(first_letters) # {'a', 'b', 'c'}
7. 生成器表达式
把方括号换成圆括号,就变成生成器:
# 列表推导式:立即生成所有元素
squares_list = [i ** 2 for i in range(10)]
print(type(squares_list)) # <class 'list'>
# 生成器表达式:惰性计算
squares_gen = (i ** 2 for i in range(10))
print(type(squares_gen)) # <class 'generator'>
# 需要时才计算
for sq in squares_gen:
print(sq, end=' ')
区别:
- 列表推导式:内存中创建完整列表
- 生成器表达式:按需生成,节省内存
大数据集用生成器更高效。
8. 实际应用
应用 1:数据清洗
# 清洗用户输入
inputs = [' Alice ', 'bob', ' Charlie\n']
cleaned = [name.strip().capitalize() for name in inputs]
print(cleaned) # ['Alice', 'Bob', 'Charlie']
应用 2:文件处理
# 读取文件并处理(假设文件存在)
with open('data.txt') as f:
numbers = [int(line.strip()) for line in f if line.strip().isdigit()]
应用 3:坐标变换
# 笛卡尔积
colors = ['红', '黑']
sizes = ['S', 'M', 'L']
products = [f"{color}-{size}" for color in colors for size in sizes]
print(products)
# ['红-S', '红-M', '红-L', '黑-S', '黑-M', '黑-L']
9. 注意事项
不要过度使用
虽然列表推导式很强大,但不要为了炫技而牺牲可读性:
# 可读性差(不推荐)
result = [[i*j for i in range(1, 10)] for j in range(1, 10) if sum([i*j for i in range(1, 10)]) > 100]
# 应该拆分成多行或用传统循环
原则:如果列表推导式超过 2 行,或者逻辑复杂,就用传统 for 循环。
避免副作用
列表推导式应该是"纯函数",不要有副作用:
# 不好的例子
count = 0
result = [count := count + 1 for _ in range(5)]
# 应该用传统循环
count = 0
result = []
for _ in range(5):
count += 1
result.append(count)
10. 小结
今天我们学习了列表推导式:
- 基本语法:
[表达式 for 变量 in 序列] - 带条件:
[表达式 for 变量 in 序列 if 条件] - if-else:
[表达式1 if 条件 else 表达式2 for 变量 in 序列] - 嵌套:多层 for 循环
- 其他推导式:字典、集合
- 生成器表达式:节省内存
列表推导式是 Python 的精髓之一,掌握它能让你的代码更 Pythonic、更优雅。但记住:清晰比简洁更重要。
练习题:
- 用列表推导式生成 1-100 中所有 3 的倍数
- 给定列表
['Python', 'Java', 'C++', 'Go'],生成一个字典,键是语言名,值是名字长度 - 用列表推导式生成一个 3×3 的单位矩阵(对角线为 1,其他为 0)
思考题:
列表推导式和传统 for 循环哪个性能更好?为什么?
本文代码示例: