一、列表推导式基础
列表推导式(list comprehension)是 Python 中一种简洁、高效地创建列表的方式。它可以把多行循环 + 条件判断压缩成一行表达式,同时保持可读性。
列表创建有三种方式:字面量方式、构造器方式、推导式方式。本次主要探讨列表的推导式方式。
基本语法
[表达式 for 变量 in 可迭代对象]
- 表达式:对每个元素进行的操作(可以是计算、函数调用、字符串格式化等)
- 可迭代对象:列表、元组、range、字符串、字典等
示例1:生成平方数列表
# 普通写法
squares = []
for i in range(1, 6):
squares.append(i ** 2)
print(squares)
# 输出: [1, 4, 9, 16, 25]
# 列表推导式
squares = [i ** 2for i in range(1, 6)]
print(squares)
# 输出: [1, 4, 9, 16, 25]
二、添加条件筛选
在推导式末尾加上 if 条件,只保留满足条件的元素。
[表达式 for 变量 in 可迭代对象 if 条件]
示例2:过滤偶数
even_nums = [x for x in range(10) if x % 2 == 0]
print(even_nums)
# 输出:[0, 2, 4, 6, 8]
三、嵌套循环
两个(或多个)for 子句,相当于扁平化的嵌套循环。
[表达式 for 变量1in 可迭代1for 变量2in 可迭代2]
示例3:二维坐标扁平化
coord_datas = [(x, y) for x in range(2) for y in range(3)]
print(coord_datas)
# 输出: [(0,0), (0,1), (0,2), (1,0), (1,1), (1,2)]
四、带有 if-else 的表达式
注意区分:if 放在 表达式内部 用于三元条件运算,放在 末尾 用于过滤。
# 三元条件:根据条件选择不同的表达式
[表达式A if 条件 else 表达式B for 变量 in 可迭代对象]
示例4:将奇数变为字符串"odd",偶数变为"Even"
result = [x for x in range(5)]
print(result) # [0, 1, 2, 3, 4]
result = ['Even'if x % 2 == 0else"odd"for x in range(5)]
print(result)
# 输出:['Even', 'odd', 'Even', 'odd', 'Even']
五、高级技巧
1. 使用函数作为表达式
import math
roots = [math.sqrt(x) for x in range(1, 6)]
print([round(r, 2) for r in roots])
# 输出: [1.0, 1.41, 1.73, 2.0, 2.24]
2. 多变量同时迭代
利用 zip 打包多个列表。
names = ["小红", "小黄", "小蓝"]
scores = [95, 87, 92]
info = [f"{name}: {score}"for name, score in zip(names, scores)]
print(info)
# 输出:['小红: 95', '小黄: 87', '小蓝: 92']
3. 从嵌套列表提取元素
# 矩阵
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
# 扁平化转换
flatten = [num for row in matrix for num in row]
print(flatten)
# 输出:[1,2,3,4,5,6,7,8,9]
六、性能提示
- 列表推导式通常比等效的
for 循环更快,因为它在底层使用 C 级别的执行。 - 但如果嵌套过多或逻辑复杂,可读性会下降,此时应拆分为普通循环。
七、趣味例子
1. 使用 random 模拟掷骰子
import random
# 生成 20 个 1~6 的随机数,只保留大于 4 的点数
high_rolls = [roll for roll in (random.randint(1, 6) for _ in range(20)) if roll > 4]
print(high_rolls)
# 输出: [5, 6, 5, 6, 6, 5]
2. 使用 math 生成勾股数
import math
# 限制 a, b 在 1~20 之间,c 为整数
triples = [(a, b, c) for a in range(1, 21) for b in range(a, 21)
for c in range(b, 21) if a**2 + b**2 == c**2]
print(triples[:5])
# 输出: [(3,4,5), (5,12,13), (6,8,10), (7,24,25), (8,15,17)]
3. 使用 itertools 生成笛卡尔积并格式化
import itertools
colors = ['红', '绿', '蓝']
sizes = ['R', 'G', 'B']
products = [f"{color}{size}"for color, size in itertools.product(colors, sizes)]
print(products)
# 输出:['红R', '红G', '红B', '绿R', '绿G', '绿B', '蓝R', '蓝G', '蓝B']
4. 使用 datetime 生成过去 7 天的日期
from datetime import datetime, timedelta
today = datetime.now()
last_7_days = [(today - timedelta(days=i)).strftime('%Y-%m-%d') for i in range(7)]
print(last_7_days)
# 输出:['2026-06-06', '2026-06-05', '2026-06-04', '2026-06-03', '2026-06-02', '2026-06-01', '2026-05-31']
5. 使用 pathlib 获取当前目录下所有 .py 文件
from pathlib import Path
py_files = [f.name for f in Path('.').iterdir() if f.suffix == '.py']
print(py_files) # ['demo.py', 'utils.py', ...]
6. 使用 string + random 生成随机密码(8 位字母数字)
import string, random
chars = string.ascii_letters + string.digits
passwords = [''.join(random.choices(chars, k=8)) for _ in range(5)]
print(passwords) # ['aB3dE9kL', 'xY7zQ2pR', ...]
7. 使用 statistics 计算多组数据的方差(模拟)
import statistics
data_sets = [[1,2,3], [4,5,6], [7,8,9]]
var_results = [statistics.variance(data) for data in data_sets]
print(var_results) # [1.0, 1.0, 1.0]
8. 模拟从 API 响应中提取字段(使用 json)
import json
api_response = '''
[
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30},
{"name": "Cathy", "age": 28}
]
'''
data = json.loads(api_response)
names = [person['name'] for person in data]
print(names) # ['Alice', 'Bob', 'Cathy']
9. 生成斐波那契数列的部分元素(演示推导式)
# 直接使用列表推导式无法递归,但可以用赋值技巧
fib = [0, 1]
[fib.append(fib[-1] + fib[-2]) for _ in range(8)] # 副作用,不推荐
print(fib)
# 输出:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
更推荐的做法:普通循环。这里仅展示列表推导式的“副作用”用法(实际不推荐)。
10. 使用 math 和列表推导式实现素数筛的变种(埃氏筛思想)
import math
defis_prime(n):
if n < 2: returnFalse
return all(n % i != 0for i in range(2, int(math.sqrt(n)) + 1))
primes = [x for x in range(2, 50) if is_prime(x)]
print(primes) # [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
八、总结
掌握列表推导式可以让你的 Python 代码更加简洁优雅,但请始终记住 “可读性优先”。如果一行写不下,就拆成几行或改用普通循环。
练习建议:尝试用列表推导式改写你最近写过的 for 循环,体会简洁与性能的提升。