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. 常见应用场景


❓ 常见问题

Q 字典和列表什么时候该用哪个?
A 如果你要通过"名字"(键)来查找数据,用字典——比如按学号查学生信息。如果你只需要"按顺序"存取数据,用列表——比如购物车商品列表。字典的查找速度远快于列表——数据量大时(上千条)差距明显。
Q discard()remove() 有什么区别?
A remove() 删除不存在的元素会报 KeyErrordiscard() 不会报错——元素存在就删除,不存在就安静地什么都不做。如果你不确定元素是否存在,用 discard() 更安全。

📖 小节


📝 作业

  1. 基础题(难度⭐):创建一个字典存储你的个人信息(姓名、年龄、城市、爱好)。用 get() 读取"职业"字段(不存在时返回"未填写")。用 items() 遍历输出所有键值对。

  2. 进阶题(难度⭐⭐):给定一个句子 "hello world hello python world hello",统计每个单词出现的次数,输出出现次数最多的单词。提示:用字典计数,用 max(dict.items(), key=lambda x: x[1]) 找出最大值。

  3. 挑战题(难度⭐⭐⭐):写一个"简易通讯录"程序。用字典存储联系人(姓名 → 电话),支持以下操作:add Alice 13800138000 添加、del Alice 删除、find Alice 查找、all 列出所有联系人。用 while True 循环,exit 退出。提示:用 split() 解析命令。

Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏