第72集:字典推导式
学习目标
- 理解字典推导式的概念和优势
- 掌握基本字典推导式的语法
- 学会使用条件表达式过滤字典
- 了解嵌套字典推导式的使用
- 掌握字典推导式与普通循环的转换
字典推导式概念
什么是字典推导式
字典推导式(Dictionary Comprehension)是Python中创建字典的简洁语法,它允许我们通过一个表达式和迭代器来快速生成字典。与列表推导式类似,字典推导式更加简洁、易读且通常性能更好。
字典推导式的优势
- 代码简洁:一行代码替代多行循环
- 性能更好:比传统for循环执行更快
- 可读性强:意图明确,易于理解
- 灵活性高:支持多种数据转换和过滤操作
基本字典推导式
基本语法结构
# 基本语法
{key_expression: value_expression for item in iterable}
# 传统for循环方式
result = {}
for item in iterable:
result[key_expression] = value_expression基本示例
# 1. 从列表创建字典
names = ["Alice", "Bob", "Charlie"]
name_length_dict = {name: len(name) for name in names}
print(f"姓名长度字典: {name_length_dict}")
# 输出: 姓名长度字典: {'Alice': 5, 'Bob': 3, 'Charlie': 7}
# 2. 创建数字平方字典
squares_dict = {x: x**2 for x in range(6)}
print(f"平方数字典: {squares_dict}")
# 输出: 平方数字典: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 3. 从两个列表创建字典
keys = ["name", "age", "city"]
values = ["张三", 25, "北京"]
person_dict = {k: v for k, v in zip(keys, values)}
print(f"个人信息字典: {person_dict}")
# 输出: 个人信息字典: {'name': '张三', 'age': 25, 'city': '北京'}
# 4. 创建字母ASCII码字典
ascii_dict = {char: ord(char) for char in "ABCDE"}
print(f"字母ASCII码: {ascii_dict}")
# 输出: 字母ASCII码: {'A': 65, 'B': 66, 'C': 67, 'D': 68, 'E': 69}
# 5. 创建月份天数字典
months = ["一月", "二月", "三月", "四月", "五月", "六月"]
days = [31, 28, 31, 30, 31, 30]
month_days = {month: day for month, day in zip(months, days)}
print(f"月份天数: {month_days}")
# 输出: 月份天数: {'一月': 31, '二月': 28, '三月': 31, '四月': 30, '五月': 31, '六月': 30}使用函数和复杂表达式
# 1. 使用数学函数
import math
angles = [0, 30, 45, 60, 90]
trig_dict = {
angle: {
"sin": round(math.sin(math.radians(angle)), 4),
"cos": round(math.cos(math.radians(angle)), 4)
}
for angle in angles
}
print(f"三角函数字典: {trig_dict}")
# 输出: 三角函数字典: {0: {'sin': 0.0, 'cos': 1.0}, 30: {'sin': 0.5, 'cos': 0.866}, ...}
# 2. 处理字符串列表
words = ["hello", "world", "python"]
word_info = {
word: {
"length": len(word),
"uppercase": word.upper(),
"reversed": word[::-1]
}
for word in words
}
print(f"单词信息字典: {word_info}")
# 输出: 单词信息字典: {'hello': {'length': 5, 'uppercase': 'HELLO', 'reversed': 'olleh'}, ...}
# 3. 从字典创建新字典
original_dict = {
"name": "张三",
"age": 25,
"score": 85,
"city": "北京"
}
new_dict = {k: v for k, v in original_dict.items()}
print(f"复制字典: {new_dict}")
# 输出: 复制字典: {'name': '张三', 'age': 25, 'score': 85, 'city': '北京'}
# 4. 复杂计算
temperatures = [0, 10, 20, 30, 40]
temp_conversion = {
"摄氏度": temp,
"华氏度": temp * 9/5 + 32,
"开尔文": temp + 273.15
}
for temp in temperatures:
print(f"{temp}°C = {temp * 9/5 + 32:.1f}°F = {temp + 273.15:.1f}K")带条件的字典推导式
基本条件语法
# 条件筛选语法
{key_expression: value_expression for item in iterable if condition}
# 传统for循环方式
result = {}
for item in iterable:
if condition:
result[key_expression] = value_expression条件筛选示例
# 1. 筛选偶数及其平方
numbers = range(1, 21)
even_squares = {num: num**2 for num in numbers if num % 2 == 0}
print(f"偶数及其平方: {even_squares}")
# 输出: 偶数及其平方: {2: 4, 4: 16, 6: 36, 8: 64, 10: 100, 12: 144, 14: 196, 16: 256, 18: 324, 20: 400}
# 2. 筛选特定长度的字符串
words = ["apple", "banana", "cherry", "date", "fig", "grape"]
short_words_dict = {word: len(word) for word in words if len(word) <= 4}
print(f"短单词字典: {short_words_dict}")
# 输出: 短单词字典: {'date': 4, 'fig': 3}
# 3. 筛选字典中的特定项
original_dict = {
"name": "张三",
"age": 25,
"score": 85,
"city": "北京",
"grade": "A"
}
filtered_dict = {k: v for k, v in original_dict.items() if isinstance(v, (int, float))}
print(f"数值类型字典: {filtered_dict}")
# 输出: 数值类型字典: {'age': 25, 'score': 85}
# 4. 处理文件扩展名
files = ["report.pdf", "data.csv", "image.jpg", "document.docx", "presentation.pptx"]
image_dict = {file: file.split('.')[-1] for file in files if file.endswith(('.jpg', '.jpeg', '.png'))}
print(f"图片文件字典: {image_dict}")
# 输出: 图片文件字典: {'image.jpg': 'jpg'}使用复杂条件
# 1. 多条件筛选
numbers = range(1, 31)
filtered_dict = {
num: num**2
for num in numbers
if num % 2 == 0 and num % 3 == 0
}
print(f"能被2和3整除的数及其平方: {filtered_dict}")
# 输出: 能被2和3整除的数及其平方: {6: 36, 12: 144, 18: 324, 24: 576, 30: 900}
# 2. 字典条件筛选
products = {
"Laptop": {"price": 1200, "category": "Electronics"},
"Book": {"price": 20, "category": "Education"},
"Headphones": {"price": 80, "category": "Electronics"},
"Pen": {"price": 2, "category": "Office"},
"Mouse": {"price": 15, "category": "Electronics"}
}
# 筛选电子产品且价格大于50的
expensive_electronics = {
name: info
for name, info in products.items()
if info["category"] == "Electronics" and info["price"] > 50
}
print(f"高价电子产品字典: {expensive_electronics}")
# 输出: 高价电子产品字典: {'Laptop': {'price': 1200, 'category': 'Electronics'}, 'Headphones': {'price': 80, 'category': 'Electronics'}}
# 3. 使用函数作为条件
def is_prime(n):
"""检查是否为质数"""
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
numbers = range(2, 31)
prime_dict = {num: num**2 for num in numbers if is_prime(num)}
print(f"质数及其平方: {prime_dict}")
# 输出: 质数及其平方: {2: 4, 3: 9, 5: 25, 7: 49, 11: 121, 13: 169, 17: 289, 19: 361, 23: 529, 29: 841}
# 4. 文本处理条件
sentences = [
"Python is powerful",
"List comprehensions are useful",
"Code should be readable",
"Programming is fun"
]
# 筛选包含特定单词的句子
python_sentences = {
i: sentence
for i, sentence in enumerate(sentences)
if "python" in sentence.lower()
}
print(f"包含Python的句子: {python_sentences}")
# 输出: 包含Python的句子: {0: 'Python is powerful'}字典推导式的高级用法
条件表达式与字典推导式
# 1. 根据条件生成不同值
numbers = range(-5, 6)
absolute_dict = {num: num if num >= 0 else -num for num in numbers}
print(f"绝对值字典: {absolute_dict}")
# 输出: 绝对值字典: {-5: 5, -4: 4, -3: 3, -2: 2, -1: 1, 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5}
# 2. 分类标签
scores = [95, 67, 82, 45, 73, 88, 52]
grade_dict = {
i: {
"score": score,
"grade": "优秀" if score >= 85
else "良好" if score >= 70
else "及格" if score >= 60
else "不及格"
}
for i, score in enumerate(scores)
}
print("成绩等级字典:")
for idx, info in grade_dict.items():
print(f" 学生{idx+1}: {info['score']}分 - {info['grade']}")
# 输出:
# 成绩等级字典:
# 学生1: 95分 - 优秀
# 学生2: 67分 - 及格
# 学生3: 82分 - 良好
# 学生4: 45分 - 不及格
# 学生5: 73分 - 良好
# 学生6: 88分 - 优秀
# 学生7: 52分 - 不及格
# 3. 处理边界情况
numbers = [1, 2, 0, -1, -2, 3, -3]
safe_division_dict = {
num: 1/num if num != 0 else "undefined"
for num in numbers
}
print(f"安全除法字典: {safe_division_dict}")
# 输出: 安全除法字典: {1: 1.0, 2: 0.5, 0: 'undefined', -1: -1.0, -2: -0.5, 3: 0.3333333333333333, -3: -0.3333333333333333}
# 4. 字符串处理
words = ["", "hello", "world", "", "python", ""]
processed_words_dict = {
i: word.upper() if word else "EMPTY"
for i, word in enumerate(words)
}
print(f"处理后的单词字典: {processed_words_dict}")
# 输出: 处理后的单词字典: {0: 'EMPTY', 1: 'HELLO', 2: 'WORLD', 3: 'EMPTY', 4: 'PYTHON', 5: 'EMPTY'}字典键值转换
# 1. 交换键和值
original_dict = {"a": 1, "b": 2, "c": 3}
swapped_dict = {v: k for k, v in original_dict.items()}
print(f"交换键值: {swapped_dict}")
# 输出: 交换键值: {1: 'a', 2: 'b', 3: 'c'}
# 2. 修改键名
original_dict = {
"first_name": "张",
"last_name": "三",
"age": 25
}
renamed_dict = {
"名" if k == "first_name" else "姓" if k == "last_name" else "年龄": v
for k, v in original_dict.items()
}
print(f"修改键名: {renamed_dict}")
# 输出: 修改键名: {'名': '张', '姓': '三', '年龄': 25}
# 3. 修改值
original_dict = {
"price1": 100,
"price2": 200,
"price3": 300
}
modified_dict = {
k: v * 1.1 for k, v in original_dict.items()
}
print(f"增加10%: {modified_dict}")
# 输出: 增加10%: {'price1': 110.0, 'price2': 220.0, 'price3': 330.0}
# 4. 同时修改键和值
original_dict = {
"item1": 10,
"item2": 20,
"item3": 30
}
transformed_dict = {
k.upper(): v * 2 for k, v in original_dict.items()
}
print(f"转换键和值: {transformed_dict}")
# 输出: 转换键和值: {'ITEM1': 20, 'ITEM2': 40, 'ITEM3': 60}字典推导式的应用案例
案例1:数据转换
# 1. 数据清洗
raw_data = {
"name": " 张三 ",
"age": " 25 ",
"city": " 北京 ",
"score": " 85 "
}
# 清洗数据:去除空格,转换类型
cleaned_data = {
k: v.strip() if isinstance(v, str) else v
for k, v in raw_data.items()
}
# 转换数值类型
cleaned_data["age"] = int(cleaned_data["age"])
cleaned_data["score"] = int(cleaned_data["score"])
print(f"清洗后的数据: {cleaned_data}")
# 输出: 清洗后的数据: {'name': '张三', 'age': 25, 'city': '北京', 'score': 85}
# 2. 数据聚合
students = [
{"name": "张三", "subject": "数学", "score": 85},
{"name": "张三", "subject": "英语", "score": 90},
{"name": "李四", "subject": "数学", "score": 78},
{"name": "李四", "subject": "英语", "score": 82},
{"name": "王五", "subject": "数学", "score": 92},
{"name": "王五", "subject": "英语", "score": 88}
]
# 按学生聚合成绩
student_scores = {}
for student in students:
name = student["name"]
if name not in student_scores:
student_scores[name] = []
student_scores[name].append(student["score"])
# 计算平均分
average_scores = {
name: sum(scores) / len(scores)
for name, scores in student_scores.items()
}
print(f"学生平均分: {average_scores}")
# 输出: 学生平均分: {'张三': 87.5, '李四': 80.0, '王五': 90.0}案例2:文本处理
# 1. 词频统计
text = "Python is great. Python is popular. Python is powerful."
words = [word.strip(". ").lower() for word in text.split()]
word_count = {}
for word in words:
word_count[word] = word_count.get(word, 0) + 1
print(f"词频统计: {word_count}")
# 输出: 词频统计: {'python': 3, 'is': 3, 'great': 1, 'popular': 1, 'powerful': 1}
# 2. 字符统计
sentence = "Hello World!"
char_count = {
char: sentence.lower().count(char)
for char in set(sentence.lower())
if char.isalpha()
}
print(f"字符统计: {char_count}")
# 输出: 字符统计: {'h': 1, 'e': 1, 'l': 3, 'o': 2, 'w': 1, 'r': 1, 'd': 1}
# 3. 首字母统计
words = ["apple", "banana", "cherry", "apricot", "blueberry", "coconut"]
first_letter_count = {}
for word in words:
first_letter = word[0].upper()
first_letter_count[first_letter] = first_letter_count.get(first_letter, 0) + 1
print(f"首字母统计: {first_letter_count}")
# 输出: 首字母统计: {'A': 2, 'B': 2, 'C': 2}案例3:配置管理
# 1. 配置转换
config = {
"database_host": "localhost",
"database_port": "5432",
"database_name": "mydb",
"cache_enabled": "true",
"cache_ttl": "3600",
"log_level": "INFO"
}
# 转换配置类型
typed_config = {
k: int(v) if k.endswith("_port") or k.endswith("_ttl")
else v.lower() == "true" if k.endswith("_enabled")
else v
for k, v in config.items()
}
print(f"类型化配置: {typed_config}")
# 输出: 类型化配置: {'database_host': 'localhost', 'database_port': 5432, 'database_name': 'mydb', 'cache_enabled': True, 'cache_ttl': 3600, 'log_level': 'INFO'}
# 2. 配置分组
grouped_config = {}
for k, v in config.items():
prefix = k.split("_")[0]
if prefix not in grouped_config:
grouped_config[prefix] = {}
grouped_config[prefix][k] = v
print(f"分组配置: {grouped_config}")
# 输出: 分组配置: {'database': {'database_host': 'localhost', 'database_port': '5432', 'database_name': 'mydb'}, 'cache': {'cache_enabled': 'true', 'cache_ttl': '3600'}, 'log': {'log_level': 'INFO'}}字典推导式与普通循环的转换
从循环转换为推导式
# 1. 简单for循环转换
# 传统方式
squares_traditional = {}
for i in range(10):
squares_traditional[i] = i ** 2
# 字典推导式
squares_comprehension = {i: i ** 2 for i in range(10)}
print(f"传统方式: {squares_traditional}")
print(f"推导式方式: {squares_comprehension}")
# 输出:
# 传统方式: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
# 推导式方式: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
# 2. 带条件的for循环转换
# 传统方式
even_numbers_traditional = {}
for i in range(1, 21):
if i % 2 == 0:
even_numbers_traditional[i] = i ** 2
# 字典推导式
even_numbers_comprehension = {i: i ** 2 for i in range(1, 21) if i % 2 == 0}
print(f"传统方式: {even_numbers_traditional}")
print(f"推导式方式: {even_numbers_comprehension}")
# 输出:
# 传统方式: {2: 4, 4: 16, 6: 36, 8: 64, 10: 100, 12: 144, 14: 196, 16: 256, 18: 324, 20: 400}
# 推导式方式: {2: 4, 4: 16, 6: 36, 8: 64, 10: 100, 12: 144, 14: 196, 16: 256, 18: 324, 20: 400}
# 3. 处理字典项的转换
# 传统方式
original_dict = {"a": 1, "b": 2, "c": 3}
uppercase_traditional = {}
for k, v in original_dict.items():
uppercase_traditional[k.upper()] = v * 2
# 字典推导式
uppercase_comprehension = {k.upper(): v * 2 for k, v in original_dict.items()}
print(f"传统方式: {uppercase_traditional}")
print(f"推导式方式: {uppercase_comprehension}")
# 输出:
# 传统方式: {'A': 2, 'B': 4, 'C': 6}
# 推导式方式: {'A': 2, 'B': 4, 'C': 6}字典推导式的局限性
何时不应使用字典推导式
# 1. 复杂逻辑不适合字典推导式
# 不推荐:过于复杂的字典推导式
complex_result = {
f"key_{x}_{y}": x**2 + y**2 if (x + y) % 2 == 0 else (x - y)**2
for x in range(5)
for y in range(5)
if x != y and (x * y) % 3 == 0
}
# 推荐:使用传统for循环
complex_result = {}
for x in range(5):
for y in range(5):
if x != y and (x * y) % 3 == 0:
if (x + y) % 2 == 0:
complex_result[f"key_{x}_{y}"] = x**2 + y**2
else:
complex_result[f"key_{x}_{y}"] = (x - y)**2
# 2. 需要调试的情况
# 不推荐:难以调试
result = {k: complex_function(k) for k in range(100) if condition(k)}
# 推荐:便于调试
result = {}
for k in range(100):
if condition(k):
try:
result[k] = complex_function(k)
except Exception as e:
print(f"Error processing {k}: {e}")
# 3. 需要打印中间结果
# 不推荐:无法打印中间结果
result = {k: process(k) for k in data}
# 推荐:可以打印调试信息
result = {}
for k in data:
print(f"Processing {k}...")
result[k] = process(k)最佳实践
使用字典推导式的建议
# 1. 保持简洁
# 推荐:简单明了
squares = {x: x**2 for x in range(10)}
# 不推荐:过于复杂
result = {k: v if condition(k, v) else default(k, v) for k, v in data.items() if filter_condition(k, v)}
# 2. 使用有意义的变量名
# 推荐:清晰的变量名
word_lengths = {word: len(word) for word in words}
# 不推荐:模糊的变量名
d = {x: len(x) for x in y}
# 3. 合理使用条件
# 推荐:简单的条件筛选
even_squares = {x: x**2 for x in range(10) if x % 2 == 0}
# 不推荐:复杂的嵌套条件
result = {k: v for k, v in data.items() if condition1(k) and condition2(v) or condition3(k, v)}
# 4. 考虑可读性
# 推荐:易于理解
name_to_age = {person["name"]: person["age"] for person in people}
# 不推荐:难以理解
result = {x["k"]: y["v"] for x, y in zip(a, b) if x["k"] in c}总结
字典推导式是Python中创建和转换字典的强大工具,它具有以下特点:
- 简洁性:一行代码完成复杂的字典创建和转换
- 高效性:通常比传统for循环执行更快
- 可读性:意图明确,易于理解
- 灵活性:支持多种数据转换和过滤操作
在使用字典推导式时,应该:
- 保持代码简洁明了
- 使用有意义的变量名
- 避免过于复杂的逻辑
- 在需要调试时使用传统for循环
通过合理使用字典推导式,可以写出更加Pythonic和高效的代码。