Python 推导式详细教程
文章目录
- [Python 推导式详细教程](#Python 推导式详细教程)
-
- 什么是推导式?
- 综合练习:一步步构建推导式
- 注意事项和最佳实践
-
- [1. 保持简洁](#1. 保持简洁)
- [2. 避免嵌套过深](#2. 避免嵌套过深)
- [3. 性能考虑](#3. 性能考虑)
- [4. 使用 walrus 运算符(Python 3.8+)](#4. 使用 walrus 运算符(Python 3.8+))
- 记忆技巧
- 小测试
什么是推导式?
推导式是Python中一种简洁、高效创建数据序列的方法。它像是把循环和条件判断压缩成一行代码。
1. 列表推导式(最常用)
基本格式 :[表达式 for 变量 in 可迭代对象 if 条件]
示例1:基础用法
python
# 创建一个包含0-9平方的列表
squares = [x**2 for x in range(10)]
print(squares) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
示例2:带条件过滤
python
# 只保留偶数
even_numbers = [x for x in range(10) if x % 2 == 0]
print(even_numbers) # [0, 2, 4, 6, 8]
# 你的示例:过滤短名字并转大写
names = ['Bob', 'Tom', 'alice', 'Jerry', 'Wendy', 'Smith']
new_names = [name.upper() for name in names if len(name) > 3]
print(new_names) # ['ALICE', 'JERRY', 'WENDY', 'SMITH']
示例3:使用函数
python
# 对每个元素应用函数
def process_number(x):
return x * 2 if x > 5 else x
numbers = [1, 3, 5, 7, 9, 11]
processed = [process_number(x) for x in numbers]
print(processed) # [1, 3, 5, 14, 18, 22]
示例4:多个变量
python
# 两个列表组合
list1 = [1, 2, 3]
list2 = ['a', 'b', 'c']
combined = [(x, y) for x in list1 for y in list2]
print(combined) # [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), ...]
2. 字典推导式
基本格式 :{键: 值 for 变量 in 可迭代对象 if 条件}
示例1:创建字典
python
# 数字及其平方的字典
squares_dict = {x: x**2 for x in range(1, 6)}
print(squares_dict) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 你的示例:字符串长度字典
listdemo = ['Google', 'Runoob', 'Taobao']
newdict = {key: len(key) for key in listdemo}
print(newdict) # {'Google': 6, 'Runoob': 6, 'Taobao': 6}
示例2:条件过滤
python
# 只处理大于10的数字
numbers = [5, 10, 15, 20]
result = {x: x*2 for x in numbers if x > 10}
print(result) # {15: 30, 20: 40}
示例3:转换现有字典
python
# 所有值加10
original = {'a': 1, 'b': 2, 'c': 3}
new_dict = {k: v+10 for k, v in original.items()}
print(new_dict) # {'a': 11, 'b': 12, 'c': 13}
3. 集合推导式
基本格式 :{表达式 for 变量 in 可迭代对象 if 条件}
特点:自动去重
示例1:创建集合
python
# 平方数的集合
squares_set = {x**2 for x in [1, 2, 2, 3, 3, 3, 4]}
print(squares_set) # {16, 1, 4, 9} - 注意:顺序可能不同,集合无序
# 你的示例:过滤特定字符
a = {x for x in 'abracadabra' if x not in 'abc'}
print(a) # 可能是 {'d', 'r'} - 无序且去重
示例2:从列表去重
python
numbers = [1, 2, 2, 3, 3, 3, 4, 5, 5]
unique_numbers = {x for x in numbers}
print(unique_numbers) # {1, 2, 3, 4, 5}
4. 生成器表达式(元组推导式)
基本格式 :(表达式 for 变量 in 可迭代对象 if 条件)
重要特点:
- 返回生成器对象,不是立即计算所有值
- 节省内存,适合大数据处理
- 一次性的,用完就不能再用
示例1:创建生成器
python
# 创建生成器对象
gen = (x**2 for x in range(5))
print(gen) # <generator object <genexpr> at 0x...>
# 逐个获取值
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 4
# 或转换为列表
remaining = list(gen)
print(remaining) # [9, 16] - 注意:前面已经取了3个值
示例2:转换为元组
python
# 你的示例:生成1-9的元组
a = (x for x in range(1, 10))
print(a) # <generator object <genexpr> at 0x...>
# 转换为元组
tuple_a = tuple(a)
print(tuple_a) # (1, 2, 3, 4, 5, 6, 7, 8, 9)
示例3:节省内存的优势
python
# 比较列表推导式和生成器表达式的内存使用
import sys
# 列表推导式 - 占用内存
list_comp = [x**2 for x in range(1000000)]
print(f"列表占用内存: {sys.getsizeof(list_comp)} 字节")
# 生成器表达式 - 占用很少内存
gen_exp = (x**2 for x in range(1000000))
print(f"生成器占用内存: {sys.getsizeof(gen_exp)} 字节")
综合练习:一步步构建推导式
练习1:处理学生成绩
python
# 原始数据:学生姓名和成绩
students = [('Alice', 85), ('Bob', 60), ('Charlie', 92), ('David', 45)]
# 步骤1:提取成绩大于等于60的学生
passed = [name for name, score in students if score >= 60]
print("及格的学生:", passed) # ['Alice', 'Bob', 'Charlie']
# 步骤2:给每个学生成绩加5分(但不超过100分)
adjusted = [(name, min(score + 5, 100)) for name, score in students]
print("调整后的成绩:", adjusted)
# 步骤3:转换为字典
student_dict = {name: score for name, score in students}
print("学生字典:", student_dict)
练习2:多个条件
python
# 创建0-20的数字列表
numbers = list(range(21))
# 找出能被2或3整除的数,但不能被5整除
result = [x for x in numbers
if (x % 2 == 0 or x % 3 == 0)
and x % 5 != 0]
print(result) # [2, 3, 4, 6, 8, 9, 12, 14, 16, 18]
注意事项和最佳实践
1. 保持简洁
python
# ✅ 好的写法:简单明了
even_squares = [x**2 for x in range(10) if x % 2 == 0]
# ❌ 不好的写法:过于复杂
# 如果逻辑太复杂,用普通循环
2. 避免嵌套过深
python
# ✅ 两层以内通常可以接受
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]
# ❌ 三层或以上考虑用其他方法
3. 性能考虑
python
# 列表推导式 vs 普通循环
# 方法1:列表推导式(更快)
result1 = [x**2 for x in range(1000)]
# 方法2:普通循环(更灵活)
result2 = []
for x in range(1000):
result2.append(x**2)
4. 使用 walrus 运算符(Python 3.8+)
python
# 在条件中赋值
data = ["apple", "banana", "cherry", "date"]
# 只保留长度大于5的字符串,并存储长度
result = [n for s in data if (n := len(s)) > 5]
print(result) # [6, 6]
记忆技巧
| 类型 | 括号 | 特点 |
|---|---|---|
| 列表推导式 | [ ] |
最常用,生成列表 |
| 字典推导式 | { : } |
生成键值对 |
| 集合推导式 | { } |
自动去重,无序 |
| 生成器表达式 | ( ) |
节省内存,一次性 |
小测试
检查你是否掌握了推导式:
python
# 1. 将下面代码改为列表推导式
result = []
for i in range(10):
if i % 2 == 0:
result.append(i * 10)
# 答案:
result = [i * 10 for i in range(10) if i % 2 == 0]
# 2. 创建字典,键为字母,值为ASCII码
letters = 'abcde'
# 答案:
ascii_dict = {letter: ord(letter) for letter in letters}
# 3. 找出两个列表的共同元素
list1 = [1, 2, 3, 4, 5]
list2 = [4, 5, 6, 7, 8]
# 答案:
common = {x for x in list1 if x in list2}
记住:推导式让代码更简洁,但不要过度使用。如果一行代码太长或太复杂,拆分成多行会更易读。