今天我们学习 Day 5:列表/字典/集合推导式。这是 Python 中最优雅和强劲的特性之一,让你用一行代码创建复杂的数据结构。
深度解析:推导式(Comprehensions)
1. 列表推导式(List Comprehensions)
传统方法:
numbers = [1, 2, 3, 4, 5]
squares = []
for num in numbers:
squares.append(num ** 2)
print(squares) # 输出: [1, 4, 9, 16, 25]
列表推导式:
numbers = [1, 2, 3, 4, 5]
squares = [num ** 2 for num in numbers]
print(squares) # 输出: [1, 4, 9, 16, 25]
2. 带条件的列表推导式
只处理偶数:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_squares = [num ** 2 for num in numbers if num % 2 == 0]
print(even_squares) # 输出: [4, 16, 36, 64, 100]
使用条件表达式:
numbers = [1, 2, 3, 4, 5]
result = ["偶数" if num % 2 == 0 else "奇数" for num in numbers]
print(result) # 输出: ['奇数', '偶数', '奇数', '偶数', '奇数']
3. 字典推导式(Dictionary Comprehensions)
传统方法:
numbers = [1, 2, 3, 4, 5]
square_dict = {}
for num in numbers:
square_dict[num] = num ** 2
print(square_dict) # 输出: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
字典推导式
numbers = [1, 2, 3, 4, 5]
square_dict = {num: num ** 2 for num in numbers}
print(square_dict) # 输出: {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
4. 集合推导式(Set Comprehensions)
传统方法:
numbers = [1, 2, 2, 3, 3, 4, 5, 5]
unique_squares = set()
for num in numbers:
unique_squares.add(num ** 2)
print(unique_squares) # 输出: {1, 4, 9, 16, 25}
集合推导式:
numbers = [1, 2, 2, 3, 3, 4, 5, 5]
unique_squares = {num ** 2 for num in numbers}
print(unique_squares) # 输出: {1, 4, 9, 16, 25}
5. 嵌套推导式
二维列表展开:
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]
创建二维矩阵:
# 创建 3x3 矩阵
matrix = [[i * 3 + j + 1 for j in range(3)] for i in range(3)]
print(matrix) # 输出: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
6. 实际应用场景
场景1:数据清洗和转换
# 从字符串中提取数字并转换为整数
data = ["价格: 100元", "重量: 2.5kg", "数量: 3个"]
numbers = [float(''.join(filter(str.isdigit, s))) for s in data]
print(numbers) # 输出: [100.0, 2.5, 3.0]
场景2:字典键值转换
# 键值交换(如果值唯一)
original = {'a': 1, 'b': 2, 'c': 3}
reversed_dict = {v: k for k, v in original.items()}
print(reversed_dict) # 输出: {1: 'a', 2: 'b', 3: 'c'}
# 键值转换(键转为大写,值加倍)
original = {'apple': 2, 'banana': 3, 'cherry': 1}
transformed = {k.upper(): v * 2 for k, v in original.items()}
print(transformed) # 输出: {'APPLE': 4, 'BANANA': 6, 'CHERRY': 2}
场景3:数据筛选和聚合
# 从学生数据中提取及格学生的姓名和分数
students = [
{'name': 'Alice', 'score': 85},
{'name': 'Bob', 'score': 45},
{'name': 'Charlie', 'score': 92},
{'name': 'David', 'score': 58}
]
passing_students = {s['name']: s['score'] for s in students if s['score'] >= 60}
print(passing_students) # 输出: {'Alice': 85, 'Charlie': 92}
7. 高级技巧和最佳实践
技巧1:使用 walrus 操作符(Python 3.8+)
data = ["apple123", "banana", "cherry456", "date"]
# 只有在包含数字时才处理
processed = [s.upper() for s in data if any(c.isdigit() for c in s)]
print(processed) # 输出: ['APPLE123', 'CHERRY456']
技巧2:多个条件组合
numbers = range(1, 21)
# 能被2或3整除,但不能被5整除的数
result = [n for n in numbers if (n % 2 == 0 or n % 3 == 0) and n % 5 != 0]
print(result) # 输出: [2, 3, 4, 6, 8, 9, 12, 14, 16, 18]
技巧3:处理嵌套数据
# 从嵌套结构中提取数据
data = [
{'items': ['apple', 'banana', 'cherry']},
{'items': ['date', 'elderberry']},
{'items': ['fig', 'grape']}
]
all_items = [item for entry in data for item in entry['items']]
print(all_items) # 输出: ['apple', 'banana', 'cherry', 'date', 'elderberry', 'fig', 'grape']
8. 性能思考
推导式一般比等效的循环更快,由于:
- 在C层优化执行
- 避免多次方法调用(如 append())
- 更少的内存分配操作
但要注意:过于复杂的推导式会影响可读性!
9. 实际项目案例
案例1:配置文件处理
def process_config(config_lines):
"""处理配置文件行,提取键值对"""
return {
line.split('=')[0].strip(): line.split('=')[1].strip()
for line in config_lines
if '=' in line and not line.strip().startswith('#')
}
# 模拟配置文件
config_lines = [
"# 数据库配置",
"host = localhost",
"port = 5432",
"user = admin",
"# 应用配置",
"debug = True"
]
config = process_config(config_lines)
print(config)
案例2:数据分析预处理
def clean_data(data_points):
"""清洗数据:去除异常值,标准化格式"""
return [
{
'timestamp': point['ts'],
'value': float(point['value']),
'status': '正常' if 0 <= float(point['value']) <= 100 else '异常'
}
for point in data_points
if point['value'].replace('.', '', 1).isdigit()
]
# 测试数据
raw_data = [
{'ts': '2023-01-01', 'value': '45.2'},
{'ts': '2023-01-02', 'value': '102.5'}, # 异常值
{'ts': '2023-01-03', 'value': 'invalid'}, # 无效数据
{'ts': '2023-01-04', 'value': '78.9'}
]
cleaned = clean_data(raw_data)
for point in cleaned:
print(point)
今日练习
练习1:基础应用
words = ['hello', 'world', 'python', 'programming']
# 使用列表推导式:创建每个单词的大写版本列表
# 你的代码 here
# 使用字典推导式:创建 {单词: 长度} 的字典
# 你的代码 here
练习2:条件筛选
numbers = [23, 45, 12, 67, 89, 34, 56, 78, 90]
# 找出所有大于50的偶数,并计算它们的平方
# 你的代码 here
练习3:实战应用
def process_student_grades(students):
"""
处理学生成绩数据,返回及格学生的新字典
格式: {学号: {'name': 姓名, 'grade': 等级}}
等级规则: >=90 A, >=80 B, >=70 C, >=60 D, <60 F
只保留及格(D及以上)的学生
"""
# 你的代码 here
pass
# 测试数据
student_data = {
'001': {'name': 'Alice', 'score': 85},
'002': {'name': 'Bob', 'score': 45},
'003': {'name': 'Charlie', 'score': 92},
'004': {'name': 'David', 'score': 78}
}
print(process_student_grades(student_data))
练习答案:
# 练习1答案:
upper_words = [word.upper() for word in words]
word_lengths = {word: len(word) for word in words}
# 练习2答案:
result = [n**2 for n in numbers if n > 50 and n % 2 == 0]
# 练习3答案:
def process_student_grades(students):
def get_grade(score):
if score >= 90: return 'A'
elif score >= 80: return 'B'
elif score >= 70: return 'C'
elif score >= 60: return 'D'
else: return 'F'
return {
sid: {'name': info['name'], 'grade': get_grade(info['score'])}
for sid, info in students.items()
if info['score'] >= 60
}
今日总结
- 列表推导式: [表达式 for 项目 in 可迭代对象 if 条件]
- 字典推导式: {键: 值 for 项目 in 可迭代对象 if 条件}
- 集合推导式: {表达式 for 项目 in 可迭代对象 if 条件}
- 优点: 简洁、高效、Pythonic
- 注意事项: 保持可读性,复杂逻辑还是用传统循环
记住:推导式让代码更优雅,但不要为了简洁而牺牲可读性!
明天我们将学习两个实用的内置函数:any() 和 all() 的使用技巧。
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END














- 最新
- 最热
只看作者