Python: 字典与集合
前两课我们学了列表和元组,它们都是"按位置"存取数据的。但现实中我们更多是按"名字"找东西——查字典按词条名找释义,查通讯录按人名找号码。字典(dict)就是干这个用的。集合(set)则是用来做数学上的集合运算。这两个东西在数据处理中非常实用。
1. 字典是什么
字典用花括号 {} 定义,里面是一组键值对(key-value pair),键和值之间用冒号隔开。
PYTHON
# 定义字典
student = {
"name": "Alice",
"age": 20,
"city": "北京"
}
print(student) # {'name': 'Alice', 'age': 20, 'city': '北京'}
print(type(student)) # <class 'dict'>
💡 把字典想象成真实字典: "键"就是词条名,"值"就是词条的解释。你查一个键,立刻拿到对应的值。在字典中查找一个元素的速度非常快——不管字典里有 10 条还是 10 万条数据,速度几乎一样。
(1) 基本操作——增删改查
PYTHON
# 创建字典
user = {}
# 添加/修改键值对
user["name"] = "Alice"
user["age"] = 25
print(user) # {'name': 'Alice', 'age': 25}
# 修改已有键的值
user["age"] = 26
print(user) # {'name': 'Alice', 'age': 26}
# 读取值
print(user["name"]) # Alice
# print(user["email"]) # KeyError!键不存在会报错
# 用 get() 安全读取——不存在时返回默认值
print(user.get("email")) # None——没找到,返回 None
print(user.get("email", "未设置")) # 未设置——指定默认值
# 删除键值对
del user["age"]
print(user) # {'name': 'Alice'}
⚠️ 注意: 直接用
字典["不存在的键"] 会报错 KeyError。用 get() 方法可以避免这个错误——找不到就返回 None 或你指定的默认值。
▶ 示例:学生信息管理(难度⭐)
PYTHON
# 用字典存储一个学生的完整信息
student = {
"name": "Bob",
"id": "2024001",
"scores": {"语文": 85, "数学": 92, "英语": 78},
"is_active": True
}
# 读取基本信息
print(f"姓名:{student['name']}")
print(f"学号:{student['id']}")
# 读取嵌套字典
math_score = student["scores"]["数学"]
print(f"数学成绩:{math_score}")
# 用 get 安全读取联系方式
phone = student.get("phone", "未填写")
print(f"电话:{phone}")
运行结果:
TEXT
📖 仅展示
姓名:Bob
学号:2024001
数学成绩:92
电话:未填写
2. 字典的常用方法
(1) 获取所有键、值、键值对
PYTHON
user = {"name": "Alice", "age": 25, "city": "北京"}
print(user.keys()) # dict_keys(['name', 'age', 'city'])
print(user.values()) # dict_values(['Alice', 25, '北京'])
print(user.items()) # dict_items([('name', 'Alice'), ('age', 25), ('city', '北京')])
# 遍历字典——最常用的方式
for key, value in user.items():
print(f"{key} = {value}")
运行结果:
TEXT
📖 仅展示
name = Alice
age = 25
city = 北京
(2) pop() 和 setdefault()
PYTHON
# pop() —— 删除并返回指定键的值
user = {"name": "Alice", "age": 25, "city": "北京"}
city = user.pop("city")
print(f"删除的城市:{city}") # 删除的城市:北京
print(user) # {'name': 'Alice', 'age': 25}
# pop() 可以指定默认值,避免 KeyError
email = user.pop("email", "无邮箱")
print(email) # 无邮箱——键不存在,返回默认值
# setdefault() —— 如果键存在返回原值,不存在则插入默认值
user = {"name": "Alice"}
result = user.setdefault("age", 18)
print(user) # {'name': 'Alice', 'age': 18}
# 如果键已经存在,setdefault 不会修改
result = user.setdefault("name", "Bob")
print(user) # {'name': 'Alice', 'age': 18}——没变
(3) update() 合并字典
PYTHON
# 合并两个字典
defaults = {"theme": "light", "lang": "zh", "font_size": 14}
custom = {"theme": "dark", "font_size": 16}
defaults.update(custom) # custom 覆盖 defaults 中的同名键
print(defaults) # {'theme': 'dark', 'lang': 'zh', 'font_size': 16}
▶ 示例:单词计数(难度⭐⭐)
PYTHON
# 统计一段文字中每个单词出现的次数
text = "apple banana apple orange banana apple"
word_count = {}
for word in text.split():
# 如果单词已在字典中,计数加1;否则设置为1
word_count[word] = word_count.get(word, 0) + 1
print(word_count) # {'apple': 3, 'banana': 2, 'orange': 1}
# 用 items() 遍历输出
for word, count in word_count.items():
print(f"{word}: {count}次")
运行结果:
TEXT
📖 仅展示
apple: 3次
banana: 2次
orange: 1次
3. 字典的遍历与嵌套
(1) 遍历字典的三种方式
PYTHON
user = {"name": "Alice", "age": 25, "city": "北京"}
# 方式1:遍历键
for key in user: # 等价于 for key in user.keys():
print(f"{key}: {user[key]}")
# 方式2:遍历值
for value in user.values():
print(value)
# 方式3:遍历键值对(最推荐)
for key, value in user.items():
print(f"{key} → {value}")
(2) 嵌套字典——字典的值也可以是字典
PYTHON
# 嵌套字典——存储多个学生信息
students = {
"1001": {"name": "Alice", "scores": [85, 90, 78]},
"1002": {"name": "Bob", "scores": [92, 88, 95]},
"1003": {"name": "Charlie", "scores": [76, 85, 82]},
}
# 遍历嵌套字典
for sid, info in students.items():
name = info["name"]
avg = sum(info["scores"]) / len(info["scores"])
print(f"{sid} {name}:平均分 {avg:.1f}")
运行结果:
TEXT
📖 仅展示
1001 Alice:平均分 84.3
1002 Bob:平均分 91.7
1003 Charlie:平均分 81.0
4. 集合是什么
集合(set)用花括号 {} 或 set() 定义,和字典很像但没有值、只有键。集合的特点是:元素唯一、无序。
PYTHON
# 定义集合
fruits = {"苹果", "香蕉", "橘子", "苹果"} # 重复的"苹果"会被自动去重
print(fruits) # {'橘子', '苹果', '香蕉'}——顺序可能不固定
# 用 set() 从列表创建
numbers = set([1, 2, 2, 3, 3, 3])
print(numbers) # {1, 2, 3}——重复元素被去重
# 空集合必须用 set(),不能用 {}({} 是空字典)
empty_set = set()
print(type(empty_set)) # <class 'set'>
💡 集合的最常用场景就是去重:
list(set(列表)) 可以快速去掉列表中重复的元素。但注意集合是无序的,去重后顺序不保留。
(1) 集合的基本操作
PYTHON
# 添加和删除
s = set()
s.add("苹果")
s.add("香蕉")
s.add("苹果") # 重复添加无效
print(s) # {'苹果', '香蕉'}
s.discard("苹果") # 删除,不存在也不会报错
print(s) # {'香蕉'}
try:
s.remove("不存在") # 会报错!
except KeyError:
print("KeyError: 元素不存在")
5. 集合运算
这是集合最强大的功能——数学上的交集、并集、差集:
PYTHON
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
# 交集 —— 同时存在于两个集合中的元素
print(a & b) # {4, 5}
print(a.intersection(b)) # 同上
# 并集 —— 两个集合中的所有元素(去重)
print(a | b) # {1, 2, 3, 4, 5, 6, 7, 8}
print(a.union(b)) # 同上
# 差集 —— 在 a 中但不在 b 中的元素
print(a - b) # {1, 2, 3}
print(a.difference(b)) # 同上
# 对称差集 —— 在 a 或 b 中但不同时在两者中
print(a ^ b) # {1, 2, 3, 6, 7, 8}
▶ 示例:用户权限分析(难度⭐⭐⭐)
PYTHON
# 模拟社交平台的用户关系
all_users = {"Alice", "Bob", "Charlie", "赵六", "孙七"}
vip_users = {"Bob", "赵六", "孙七"}
blocked_users = {"赵六"}
# 找出"不是 VIP 的正常用户"
normal_users = all_users - vip_users - blocked_users
print(f"普通用户:{normal_users}")
# 找出"可用的 VIP(未被封禁)"
active_vip = vip_users - blocked_users
print(f"可用VIP:{active_vip}")
# 找出"被封禁的用户是否在 VIP 中"
blocked_vip = vip_users & blocked_users
print(f"被封VIP:{blocked_vip}")
# 找出"所有需要通知的用户(VIP + 被封禁)"
notify_users = vip_users | blocked_users
print(f"需通知用户:{notify_users}")
运行结果:
TEXT
📖 仅展示
普通用户:{'Alice', 'Charlie'}
可用VIP:{'Bob', '孙七'}
被封VIP:{'赵六'}
需通知用户:{'Bob', '赵六', '孙七'}
6. 常见应用场景
- 配置管理:字典存储配置参数(键=设置名,值=设置值),用
get()读取时提供默认值。 - 频率统计:用字典做计数器——每次遇到元素时
dict[key] = dict.get(key, 0) + 1。 - 数据分组:嵌套字典
{"部门": [员工列表]},按部门归集数据。 - 去重处理:集合自动去重,
list(set(data))快速去重不保留顺序,dict.fromkeys(data)去重保留顺序。 - 权限检查:集合运算判断用户权限——交集查交集权限,差集查缺失权限。
❓ 常见问题
Q 字典和列表什么时候该用哪个?
A 如果你要通过"名字"(键)来查找数据,用字典——比如按学号查学生信息。如果你只需要"按顺序"存取数据,用列表——比如购物车商品列表。字典的查找速度远快于列表——数据量大时(上千条)差距明显。
Q
discard() 和 remove() 有什么区别?A
remove() 删除不存在的元素会报 KeyError。discard() 不会报错——元素存在就删除,不存在就安静地什么都不做。如果你不确定元素是否存在,用 discard() 更安全。📖 小节
- 字典用
{}定义,存储键值对,通过键快速查找值 - 基本操作:
dict[key]读取/写入、get()安全读取、del删除 - 常用方法:
keys()、values()、items()遍历、pop()删除并返回、update()合并 setdefault()键存在返回值,不存在则插入默认值- 字典的值可以是任何类型,包括列表和字典——实现嵌套结构
- 集合用
{}或set()定义,元素唯一、无序,主要用于去重和数学运算 - 集合运算:
&交集、|并集、-差集、^对称差集
📝 作业
-
基础题(难度⭐):创建一个字典存储你的个人信息(姓名、年龄、城市、爱好)。用
get()读取"职业"字段(不存在时返回"未填写")。用items()遍历输出所有键值对。 -
进阶题(难度⭐⭐):给定一个句子
"hello world hello python world hello",统计每个单词出现的次数,输出出现次数最多的单词。提示:用字典计数,用max(dict.items(), key=lambda x: x[1])找出最大值。 -
挑战题(难度⭐⭐⭐):写一个"简易通讯录"程序。用字典存储联系人(姓名 → 电话),支持以下操作:
add Alice 13800138000添加、del Alice删除、find Alice查找、all列出所有联系人。用while True循环,exit退出。提示:用split()解析命令。