Python 字典 — 键值对存储
学习字典的创建、访问、修改 · 难度:入门 · +10XP
Python 字典 — 键值对的魔法
一、什么是字典?为什么它是 Python 的"瑞士军刀"?
字典(Dictionary,简称 dict)是 Python 中最重要、最高效的数据结构之一。它是键值对(Key-Value Pair)的集合:每个元素由一个唯一的键(key)和对应的值(value)组成。你可以把字典想象成一本真正的字典:你要查"苹果"这个词(键),就能找到它的定义(值)。查找速度极快,不管字典有多大。
为什么字典如此重要?
- O(1) 平均查找时间 — 基于哈希表实现,查找速度不随数据量增长
- 自然的映射关系 — 用户名→用户信息、商品ID→商品详情、配置项→配置值
- JSON 的原生映射 — JSON 对象和 Python 字典结构几乎一致,API 开发必备
- Python 3.7+ 保证插入顺序 — 字典按插入顺序保持键的顺序
- Django ORM 的查询结果、pandas DataFrame 的底层、FastAPI 的请求体解析……都依赖字典
二、字典 vs 列表 vs 集合 — 何时用哪个?
| 需求 | 用列表 | 用字典 | 用集合 |
|---|---|---|---|
| 按键查找数据 | 慢(O(n)) | 快(O(1)) | 不支持 |
| 保持顺序 | 是 | 是(3.7+) | 否 |
| 去重 | 需手动 | 键天然唯一 | 自动去重 |
| 存储关系 | 无 | 键值映射 | 无 |
| 典型场景 | 待办列表、时间序列 | 配置、缓存、JSON 数据 | 标签、去重 |
三、字典方法速查表
| 方法 | 功能 | 安全获取? |
|---|---|---|
| d[key] | 通过键获取值 | 否(键不存在会 KeyError) |
| d.get(key, default) | 安全获取,键不存在返回默认值 | 是(推荐!) |
| d[key] = value | 设置/更新键值 | — |
| d.setdefault(key, default) | 键存在返回原值,不存在则设置默认值 | 是 |
| d.update(d2) | 合并另一个字典 | — |
| d.pop(key, default) | 删除并返回键的值 | 有默认值则安全 |
| d.popitem() | 删除并返回最后一项(LIFO) | 否(空字典会报错) |
| d.keys() | 返回所有键的视图 | — |
| d.values() | 返回所有值的视图 | — |
| d.items() | 返回所有键值对的视图 | — |
| d.clear() | 清空字典 | — |
| del d[key] | 删除指定键 | 否(键不存在会 KeyError) |
| key in d | 检查键是否存在 | — |
四、详细代码示例(逐行注释)
# ======== 1. 创建字典的多种方式 ========
# 花括号创建(最常用)
user = {"name": "小明", "age": 18, "city": "北京"}
# dict() 构造函数
user2 = dict(name="小红", age=20, city="上海") # 键名自动转为字符串
# 从键值对列表创建
pairs = [("a", 1), ("b", 2), ("c", 3)]
d = dict(pairs) # {'a': 1, 'b': 2, 'c': 3}
# 字典推导式(Dict Comprehension)
squares = {x: x**2 for x in range(6)} # {0:0, 1:1, 2:4, 3:9, 4:16, 5:25}
# 用 fromkeys 创建(所有值相同)
defaults = dict.fromkeys(["name", "age", "city"], "未知")
# {'name': '未知', 'age': '未知', 'city': '未知'}
# ======== 2. 访问和修改 ========
user = {"name": "小明", "age": 18}
print(user["name"]) # "小明" — 直接索引(键不存在会报错!)
print(user.get("email", "未设置")) # "未设置" — 安全获取,推荐!
# 添加/更新
user["email"] = "xiaoming@example.com" # 添加新键值对
user["age"] = 19 # 更新已有键的值
# 批量更新
user.update({"age": 20, "phone": "13800138000"})
# ======== 3. 删除 ========
email = user.pop("email", "未找到") # 删除并返回,键不存在返回默认值
del user["phone"] # 直接删除(键不存在会报错)
last_item = user.popitem() # 删除并返回最后一项 (key, value)
# ======== 4. 遍历字典 ========
user = {"name": "小明", "age": 18, "city": "北京"}
# 遍历键
for key in user: # 默认为遍历键
print(key, "→", user[key])
# 遍历值
for value in user.values():
print(value)
# 同时遍历键和值(最常用!)
for key, value in user.items():
print(f"{key}: {value}")
# 带索引遍历
for i, (key, value) in enumerate(user.items()):
print(f"{i+1}. {key} = {value}")
# ======== 5. 字典的核心操作 ========
# 检查键是否存在
if "name" in user: # O(1) 时间复杂度
print("name 存在于字典中")
# 默认值字典(计数神器!)
text = "hello world hello python"
word_count = {}
for word in text.split():
# 如果键不存在,先设置默认值 0,再加 1
word_count[word] = word_count.get(word, 0) + 1
print(word_count) # {'hello': 2, 'world': 1, 'python': 1}
# ======== 6. defaultdict — 更优雅的默认值 ========
from collections import defaultdict
# 自动为不存在的键创建默认值
word_count2 = defaultdict(int) # int() 返回 0
for word in text.split():
word_count2[word] += 1 # 不需要 get 了!
print(dict(word_count2))
# 分组列表
students = [
{"name": "小明", "grade": "A"},
{"name": "小红", "grade": "B"},
{"name": "小刚", "grade": "A"},
]
by_grade = defaultdict(list) # list() 返回空列表
for student in students:
by_grade[student["grade"]].append(student["name"])
print(dict(by_grade)) # {'A': ['小明', '小刚'], 'B': ['小红']}
# ======== 7. 字典合并(Python 3.9+ 新特性) ========
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4} # 注意 b 键冲突
merged = d1 | d2 # {'a': 1, 'b': 3, 'c': 4} — 后者覆盖前者
d1 |= d2 # 就地合并,d1 被修改
# Python 3.5-3.8 的合并方式
merged_old = {**d1, **d2} # 解包合并
# ======== 8. 嵌套字典 ========
config = {
"database": {
"host": "localhost",
"port": 3306,
"name": "mydb"
},
"server": {
"host": "0.0.0.0",
"port": 8080
}
}
# 安全访问嵌套值
db_host = config.get("database", {}).get("host", "默认值")
# 避免写成 config["database"]["host"](中间任何一层为 None 就崩溃)
# ======== 9. 字典排序 ========
scores = {"小明": 85, "小红": 92, "小刚": 78}
# 按键排序
sorted_by_key = dict(sorted(scores.items()))
# 按值排序(降序)
sorted_by_val = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))
print(sorted_by_val) # {'小红': 92, '小明': 85, '小刚': 78}
五、实践任务
- 创建一个字典存储个人信息(姓名、年龄、城市、爱好列表),遍历并打印所有键值对
- 统计字符串
"apple banana apple orange banana apple"中每个单词出现的次数,用字典存储结果 - 使用
defaultdict(list)将学生按成绩等级分组:[("小明","A"), ("小红","B"), ("小刚","A"), ("小丽","C")] - 编写函数
merge_dicts(*dicts),合并任意数量的字典(后面覆盖前面) - 给定嵌套字典,安全获取
data["user"]["profile"]["avatar"],如果任何一层不存在则返回"default.png"