列表推导式(List Comprehension)是Python中最优雅、最强大的特性之一。它让我们能用一行简洁的代码完成原本需要多行循环的任务。本文将带你从基础到高级,全面掌握这一Python核心技巧。
什么是列表推导式?
列表推导式是一种简洁的语法,用于基于现有列表创建新列表。它将循环和条件判断压缩成一行代码,既提高了代码可读性,也提升了执行效率。
传统方法 vs 列表推导式:
# 传统方法
squares = []
for i in range(10):
squares.append(i ** 2)
# 列表推导式
squares = [i ** 2 for i in range(10)]
基础语法
列表推导式的基本结构:
[expression for item in iterable]
示例1:转换数据类型
# 将字符串列表转换为整数
strings = ['1', '2', '3', '4', '5']
numbers = [int(x) for x in strings]
print(numbers) # [1, 2, 3, 4, 5]
示例2:字符串操作
# 将所有单词转换为大写
words = ['hello', 'world', 'python']
upper_words = [word.upper() for word in words]
print(upper_words) # ['HELLO', 'WORLD', 'PYTHON']
添加条件过滤
列表推导式可以包含条件语句,用于过滤元素。
语法结构:
[expression for item in iterable if condition]
示例3:过滤偶数
# 获取0-20之间的所有偶数
evens = [x for x in range(21) if x % 2 == 0]
print(evens) # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
示例4:过滤字符串
# 只保留长度大于3的单词
words = ['cat', 'elephant', 'dog', 'butterfly']
long_words = [word for word in words if len(word) > 3]
print(long_words) # ['elephant', 'butterfly']
条件表达式(if-else)
当需要根据条件选择不同的表达式时,使用三元运算符:
语法结构:
[expression_if_true if condition else expression_if_false for item in iterable]
示例5:标记正负数
numbers = [-2, -1, 0, 1, 2]
labels = ['negative' if x < 0 else 'positive' if x > 0 else 'zero' for x in numbers]
print(labels) # ['negative', 'negative', 'zero', 'positive', 'positive']
示例6:数据清洗
# 将None替换为默认值
data = [10, None, 20, None, 30]
cleaned = [x if x is not None else 0 for x in data]
print(cleaned) # [10, 0, 20, 0, 30]
嵌套列表推导式
列表推导式可以嵌套使用,处理多维数据结构。
示例7:展平二维列表
# 将二维列表转换为一维列表
matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
flattened = [num for row in matrix for num in row]
print(flattened) # [1, 2, 3, 4, 5, 6, 7, 8, 9]
示例8:创建矩阵
# 创建3x3的矩阵
matrix = [[i * 3 + j for j in range(3)] for i in range(3)]
print(matrix) # [[0, 1, 2], [3, 4, 5], [6, 7, 8]]
示例9:矩阵转置
# 转置矩阵
matrix = [[1, 2, 3], [4, 5, 6]]
transposed = [[row[i] for row in matrix] for i in range(len(matrix[0]))]
print(transposed) # [[1, 4], [2, 5], [3, 6]]
字典推导式
类似于列表推导式,Python也支持字典推导式:
示例10:创建字典
# 创建数字与其平方的映射
squares_dict = {x: x**2 for x in range(6)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
示例11:字典键值互换
# 交换字典的键和值
original = {'a': 1, 'b': 2, 'c': 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
示例12:过滤字典
# 只保留值大于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}
集合推导式
集合推导式用于创建集合(去重):
示例13:去重操作
# 从列表中提取唯一值
numbers = [1, 2, 2, 3, 3, 3, 4, 4, 5]
unique = {x for x in numbers}
print(unique) # {1, 2, 3, 4, 5}
高级技巧
技巧1:使用enumerate获取索引
# 同时获取索引和值
words = ['apple', 'banana', 'cherry']
indexed = [(i, word) for i, word in enumerate(words)]
print(indexed) # [(0, 'apple'), (1, 'banana'), (2, 'cherry')]
技巧2:多个迭代器组合
# 使用zip同时遍历多个列表
names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
combined = [f"{name} is {age} years old" for name, age in zip(names, ages)]
print(combined) # ['Alice is 25 years old', 'Bob is 30 years old', 'Charlie is 35 years old']
技巧3:链式调用方法
# 组合多个字符串方法
text = " hello world "
processed = [word.strip().capitalize() for word in [text]]
print(processed) # ['Hello world']
技巧4:使用函数
# 在推导式中调用函数
def is_prime(n):
if n < 2:
return False
return all(n % i != 0 for i in range(2, int(n**0.5) + 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]
技巧5:嵌套条件
# 多个过滤条件
numbers = range(1, 101)
result = [x for x in numbers if x % 3 == 0 if x % 5 == 0]
print(result) # [15, 30, 45, 60, 75, 90]
性能优势
列表推导式通常比传统循环更快:
import timeit
# 传统方法
def traditional():
result = []
for i in range(1000):
result.append(i ** 2)
return result
# 列表推导式
def comprehension():
return [i ** 2 for i in range(1000)]
# 性能测试
print(timeit.timeit(traditional, number=10000)) # 约 0.5秒
print(timeit.timeit(comprehension, number=10000)) # 约 0.4秒
最佳实践
✅ 推荐做法
- 保持简洁:如果推导式过于复杂,考虑使用传统循环
- 使用有意义的变量名:即使在简短的推导式中也要清晰
- 单一职责:每个推导式只做一件事
# 好的例子
valid_emails = [email for email in emails if '@' in email]
❌ 避免的做法
- 过度嵌套:超过两层嵌套会降低可读性
- 复杂逻辑:不要在推导式中放入过多逻辑
- 副作用:避免在推导式中修改外部状态
# 不好的例子(过于复杂)
result = [x**2 if x > 0 else -x**2 if x < 0 else 0 for x in [y**2 for y in range(-10, 10) if y % 2 == 0] if abs(x) > 5]
# 改进:拆分为多步
squared = [y**2 for y in range(-10, 10) if y % 2 == 0]
result = [x**2 if x > 0 else -x**2 if x < 0 else 0 for x in squared if abs(x) > 5]
常见陷阱
陷阱1:变量作用域
# 推导式中的变量不会泄漏到外部作用域(Python 3)
[x for x in range(5)]
# print(x) # 这会报错:NameError
陷阱2:内存消耗
对于大数据集,考虑使用生成器表达式:
# 列表推导式(立即创建所有元素)
squares_list = [x**2 for x in range(1000000)] # 占用大量内存
# 生成器表达式(惰性求值)
squares_gen = (x**2 for x in range(1000000)) # 节省内存
实战案例
案例1:数据清洗
# 清洗和标准化用户输入
user_inputs = [' Alice ', 'bob', ' CHARLIE', 'david ']
cleaned = [name.strip().capitalize() for name in user_inputs]
print(cleaned) # ['Alice', 'Bob', 'Charlie', 'David']
案例2:文件处理
# 读取文件并处理每一行
# lines = [line.strip() for line in open('data.txt') if line.strip()]
案例3:数据转换
# 将CSV风格的字符串转换为字典列表
data = "name,age\nAlice,25\nBob,30"
lines = data.split('\n')
headers = lines[0].split(',')
records = [dict(zip(headers, line.split(','))) for line in lines[1:]]
print(records) # [{'name': 'Alice', 'age': '25'}, {'name': 'Bob', 'age': '30'}]
总结
列表推导式是Python的精华特性之一,它让代码更加简洁和Pythonic。掌握列表推导式的关键点:
- 基础语法:
[expression for item in iterable] - 条件过滤:添加
if条件筛选元素 - 条件表达式:使用三元运算符处理不同情况
- 嵌套使用:处理多维数据结构
- 扩展应用:字典推导式、集合推导式
- 性能考虑:通常比循环更快,但大数据集考虑生成器
- 可读性优先:复杂逻辑时使用传统循环
延伸阅读:
- Python官方文档:List Comprehensions
- PEP 202:List Comprehensions提案
- 生成器表达式与列表推导式的性能对比
1040

被折叠的 条评论
为什么被折叠?



