第十二篇:dict 与 set——字典与集合完全指南
前言
**字典(dict)和集合(set)**是 Python 中两种强大的关联数据结构。字典通过键值对实现 O(1) 的查找效率,集合用于高效去重和数学集合运算。本文全面讲解它们的创建、增删改查、遍历方法以及性能特点。
字典(dict)基础
创建方式
# 字面量创建
empty = {}
student = {"name": "小明", "age": 25, "score": 92}
# 用 dict() 构造函数
pairs = [("name", "小明"), ("age", 25)]
from_pairs = dict(pairs)
# 关键字参数创建(键必须是字符串)
user = dict(name="小红", age=22, city="北京")
len() 函数
user = {"name": "小明", "age": 25, "city": "北京"}
print(len(user)) # 3 — 键值对数量
dict 的基本操作
索引访问与安全获取
student = {"name": "小明", "age": 25, "score": 92}
# ❌ 直接访问:键不存在则 KeyError
# print(student["grade"]) # KeyError!
# ✅ get() 安全访问,支持默认值
print(student.get("name")) # 小明
print(student.get("grade")) # None
print(student.get("grade", "N/A")) # N/A
添加和修改
student = {"name": "小明", "age": 25}
# 直接赋值(新键则添加,已有键则修改)
student["grade"] = "三年级"
student["age"] = 26
# update() 批量更新
student.update({"score": 95, "city": "北京"})
print(student) # {..., "score": 95, "city": "北京"}
删除元素
# pop() — 按键删除并返回值
age = student.pop("age")
print(age) # 25
print(student) # 不含 age 键
# pop() 设置默认值(防止 KeyError)
missing = student.pop("grade", "未知")
print(missing) # 未知
# popitem() — 弹出最后一个键值对
last = student.popitem()
# del 删除指定键
del student["name"]
# clear() 清空整个字典
student.clear()
常用方法速查
student = {"name": "小明", "age": 25, "score": 92}
# keys()/values()/items()
for key in student.keys(): pass
for value in student.values(): pass
for key, value in student.items(): print(f"{key}: {value}")
# setdefault() — 键存在返回值,否则添加默认值
result = student.setdefault("grade", "一年级")
# copy() 浅拷贝
copy_student = student.copy()
成员检查
print("name" in student) # True — 检查的是键
print("小明" in student.values()) # True — 需要遍历
字典推导式
# 基本形式:{键表达式: 值表达式 for ...}
squares = {x: x ** 2 for x in range(1, 6)}
print(squares) # {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 带过滤条件
evens = {x: x ** 2 for x in range(1, 11) if x % 2 == 0}
print(evens) # {2: 4, 4: 16, 6: 36, 8: 64, 10: 100}
# 从现有字典推导
upper_names = {k.upper(): v for k, v in student.items()}
# 嵌套字典
matrix = {(i, j): i * j for i in range(1, 4) for j in range(1, 4)}
集合(set)基础
创建方式
# ⚠️ 空集合必须用 set()!{} 是空字典
empty = set()
# 创建含元素的集合
colors = {"red", "green", "blue"}
# 从列表创建(自动去重)
duplicates = [1, 2, 2, 3, 3, 3, 4]
unique = set(duplicates)
print(unique) # {1, 2, 3, 4}
len() 函数
print(len(colors)) # 元素个数
集合的基本操作
添加和删除
colors = {"红", "绿", "蓝"}
# add() — 添加单个元素(不重复)
colors.add("黄")
colors.add("红") # 无变化
# update() — 批量添加
colors.update(["白", "黑", "灰"])
# remove() — 删除(不存在抛 KeyError)
colors.remove("红")
# discard() — 删除(不存在也不报错)
colors.discard("橙")
# pop() — 删除并返回任意元素
removed = colors.pop()
# clear() 清空
colors.clear()
frozenset 不可变集合
# frozenset 不可变,可以作为字典键或嵌套集合的元素
fs = frozenset([1, 2, 3])
# fs.add(4) # AttributeError!
# 用法:作为字典的键
data = {frozenset(["a", "b"]): 1, frozenset(["c", "d"]): 2}
print(data[frozenset(["a", "b"])]) # 1
集合的数学运算
交并差集速查
| 操作 | 运算符 | 方法 | 含义 |
|---|---|---|---|
| 交集 | & |
.intersection() |
共同元素 |
| 并集 | | |
.union() |
所有元素(去重) |
| 差集 | - |
.difference() |
在 A 但不在 B |
| 对称差 | ^ |
.symmetric_difference() |
只在一个集合中 |
a = {1, 2, 3, 4, 5}
b = {4, 5, 6, 7, 8}
print(a & b) # {4, 5} — 交集
print(a | b) # {1, 2, 3, 4, 5, 6, 7, 8} — 并集
print(a - b) # {1, 2, 3} — 差集
print(a ^ b) # {1, 2, 3, 6, 7, 8} — 对称差
子集和超集
base = {1, 2, 3, 4, 5}
subset = {1, 2, 3}
superset = {1, 2, 3, 4, 5, 6}
print(subset.issubset(base)) # True
print(base.issuperset(subset)) # True
print(subset < base) # True — 真子集
print(base > subset) # True — 真超集
# 不相交检查
a = {1, 2, 3}
b = {4, 5, 6}
print(a.isdisjoint(b)) # True — 没有共同元素
集合推导式
# 基本形式
squares = {x ** 2 for x in range(1, 6)}
print(squares) # {1, 4, 9, 16, 25}
# 过滤条件 + 去重
vowels = {"a", "e", "i", "o", "u"}
words = ["apple", "banana", "cherry"]
word_vowels = {char for word in words for char in word if char in vowels}
print(word_vowels) # {'a', 'e'} — 自动去重
dict vs set 对比总结
| 特性 | dict | set |
|---|---|---|
| 存储单位 | 键值对 | 单一元素 |
| 语法 | {"key": "val"} |
{"elem"} |
| 可变性 | 元素可变 | 元素可变 |
| 哈希要求 | 键必须可哈希 | 元素必须可哈希 |
| 用途 | 快速查找映射 | 去重、集合运算 |
何时用哪个?
# ✅ 用 dict:数据之间存在映射关系
user_info = {"name": "小明", "age": 25}
counter = {"click": 100, "view": 500}
lookup = {str(i): f"数字{i}" for i in range(10)}
# ✅ 用 set:需要去重或集合运算
seen_pages = set()
allowed_tags = {"python", "web", "ai"}
common_users = users_a & users_b # 求交集
实战示例
词频统计
def count_words(text):
words = text.lower().split()
counter = {}
for word in words:
clean = word.strip(".,!?;:'()-")
if clean:
counter[clean] = counter.get(clean, 0) + 1
return counter
text = "Python is great. Python is fun. Is Python the best?"
freq = count_words(text)
print(freq)
# {'python': 3, 'is': 2, 'great': 1, 'fun': 1, 'the': 1, 'best': 1}
嵌套字典成绩管理
students = {
"张三": {"math": 95, "english": 88},
"李四": {"math": 72, "english": 91},
}
print(students["张三"]["math"]) # 95
subjects = ["math", "english"]
for subject in subjects:
total = sum(s[subject] for s in students.values())
avg = total / len(students)
print(f"{subject} 平均分:{avg:.1f}")
defaultdict 简化代码
from collections import defaultdict
# 普通字典遇到不存在键会报错
# groups = {}
# groups[item[0]].append(item) # KeyError!
# defaultdict 自动创建默认值
groups = defaultdict(list)
for item in ["apple", "apricot", "banana", "blueberry"]:
groups[item[0]].append(item)
print(dict(groups))
# {'a': ['apple', 'apricot'], 'b': ['banana', 'blueberry']}
双重循环找重复项
def find_duplicates(items):
seen = set()
duplicates = set()
for item in items:
if item in seen:
duplicates.add(item)
else:
seen.add(item)
return duplicates
print(find_duplicates([1, 2, 3, 2, 4, 1, 5, 3])) # {1, 2, 3}
性能特点
为什么 dict/set 这么快?
Python 的 dict 和 set 底层基于哈希表(Hash Table):
import timeit
large_dict = {i: f"value_{i}" for i in range(1_000_000)}
start = timeit.default_timer()
_ = large_dict[999999] # 瞬间完成
print("dict 查找耗时:毫秒级")
large_list = list(range(1_000_000))
start = timeit.default_timer()
_ = 999999 in large_list # 线性时间
print("list 查找耗时:随规模增长")
哈希约束
# ✅ 可哈希(不可变类型)
hashable_items = {1, "hello", (1, 2), 3.14, True, None}
my_dict = {1: "one", "hello": "world", (1, 2): "tuple_key"}
# ❌ 不可哈希(不能作为 dict 的键或 set 的元素)
# unhashable = {[1, 2]} # TypeError
# bad_dict = {[1, 2]: "value"} # TypeError
总结
本文涵盖了 Python dict 和 set 的核心知识:
- dict 基础 — 三种创建方式、len()
- 增删改查 — 直接赋值、update()/pop()/del()/get()/setdefault()/clear()
- 遍历方法 — keys()/values()/items()
- 成员检查 — in/not in 只检查键
- 字典推导式 — 简洁高效的创建方式
- set 基础 — 创建(注意 set() ≠ {})、add()/remove()/discard()/pop()/clear()
- frozenset — 不可变集合,可作为字典键
- 数学运算 — 交(&)、并(|)、差(-)、对称差(^)、子集/超集、不相交
- 集合推导式 — 自动去重
- 性能 — 哈希表 O(1) 查找 vs list O(n)
- 实用技巧 — defaultdict、嵌套字典、找重复项
下一篇文章将深入讲解类与实例:面向对象编程基础。
本文是 Python 教程系列的第十二篇。
