Python 字典与集合
目录
学习目标
- 掌握字典的创建、访问、增删改查操作
- 理解集合的特性和数学运算
- 学会字典推导式和集合推导式
- 了解哈希表的基本原理
一、字典(dict)
字典是 Python 中用于存储键值对的数据结构,它是无序的(Python 3.7+ 实际保持插入顺序)、键唯一的映射类型。
1.1 创建字典
# 直接创建
user = {"name": "Alice", "age": 25, "city": "Beijing"}
# 使用 dict() 构造函数
user2 = dict(name="Bob", age=30, city="Shanghai")
# 从键值对序列创建
user3 = dict([("name", "Charlie"), ("age", 35)])
# 空字典
empty = {}
empty2 = dict()
# 使用 fromkeys() 创建带默认值的字典
keys = ["a", "b", "c"]
d = dict.fromkeys(keys, 0)
print(d) # {'a': 0, 'b': 0, 'c': 0}1.2 访问和修改
user = {"name": "Alice", "age": 25, "city": "Beijing"}
# 访问
print(user["name"]) # Alice
# print(user["gender"]) # KeyError!
# 安全访问
print(user.get("gender")) # None
print(user.get("gender", "未知")) # 未知(默认值)
# 修改和添加
user["age"] = 26 # 修改已有键
user["gender"] = "female" # 添加新键
print(user)
# 批量更新
user.update({"phone": "123456", "email": "alice@example.com"})
print(user)
# 使用 setdefault:键不存在时设置默认值
user.setdefault("country", "China")
print(user["country"]) # China
user.setdefault("country", "USA") # 已存在,不修改
print(user["country"]) # China1.3 删除操作
user = {"name": "Alice", "age": 25, "city": "Beijing"}
# 删除指定键
del user["city"]
print(user) # {'name': 'Alice', 'age': 25}
# pop() 删除并返回值
age = user.pop("age")
print(age, user) # 25 {'name': 'Alice'}
# popitem() 删除并返回最后一个键值对(Python 3.7+ 按插入顺序)
last = user.popitem()
print(last) # ('name', 'Alice')
# clear() 清空
user.clear()
print(user) # {}1.4 遍历字典
user = {"name": "Alice", "age": 25, "city": "Beijing"}
# 遍历键
for key in user:
print(key)
# 遍历值
for value in user.values():
print(value)
# 遍历键值对
for key, value in user.items():
print(f"{key}: {value}")
# 检查键是否存在
print("name" in user) # True
print("gender" in user) # False二、字典的高级用法
2.1 嵌套字典
school = {
"class_a": {
"teacher": "Mr. Wang",
"students": ["Alice", "Bob"]
},
"class_b": {
"teacher": "Ms. Li",
"students": ["Charlie", "David"]
}
}
print(school["class_a"]["teacher"]) # Mr. Wang
print(school["class_b"]["students"][0]) # Charlie2.2 字典合并(Python 3.9+)
d1 = {"a": 1, "b": 2}
d2 = {"b": 3, "c": 4}
# | 合并(3.9+)
merged = d1 | d2
print(merged) # {'a': 1, 'b': 3, 'c': 4}
# |= 就地合并
d1 |= d2
print(d1) # {'a': 1, 'b': 3, 'c': 4}2.3 字典排序
scores = {"Alice": 85, "Bob": 92, "Charlie": 78}
# 按键排序
sorted_by_key = dict(sorted(scores.items()))
print(sorted_by_key) # {'Alice': 85, 'Bob': 92, 'Charlie': 78}
# 按值排序
sorted_by_value = dict(sorted(scores.items(), key=lambda x: x[1], reverse=True))
print(sorted_by_value) # {'Bob': 92, 'Alice': 85, 'Charlie': 78}三、集合(set)
集合是一个无序、不重复的元素集合,支持数学上的集合运算。
3.1 创建集合
# 直接创建
s = {1, 2, 3, 3, 3} # 重复自动去重
print(s) # {1, 2, 3}
# 使用 set() 构造函数
s2 = set([1, 2, 3, 3, 3]) # 从列表创建
print(s2) # {1, 2, 3}
# 空集合(注意:{} 是空字典!)
empty_set = set()
print(type(empty_set)) # <class 'set'>3.2 集合操作
s = {1, 2, 3}
# 添加元素
s.add(4)
print(s) # {1, 2, 3, 4}
# 批量添加
s.update([5, 6])
print(s) # {1, 2, 3, 4, 5, 6}
# 删除元素
s.remove(6) # 元素不存在会报错
s.discard(100) # 元素不存在不报错
popped = s.pop() # 随机删除并返回一个元素
print(s)
s.clear() # 清空3.3 集合运算
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# 并集
print(a | b) # {1, 2, 3, 4, 5, 6}
print(a.union(b))
# 交集
print(a & b) # {3, 4}
print(a.intersection(b))
# 差集
print(a - b) # {1, 2}
print(a.difference(b))
# 对称差集(只在其中一个集合中的元素)
print(a ^ b) # {1, 2, 5, 6}
print(a.symmetric_difference(b))
# 子集和超集
print({1, 2} < a) # True(真子集)
print({1, 2, 3} <= a) # True(子集)
print(a > {1, 2}) # True(真超集)3.4 不可变集合 frozenset
# frozenset 不可变,可作为字典的键
fs = frozenset([1, 2, 3])
# fs.add(4) # AttributeError!
# 可用作字典键
mapping = {frozenset([1, 2]): "A", frozenset([3, 4]): "B"}
print(mapping[frozenset([1, 2])]) # A四、推导式
4.1 字典推导式
# 基本字典推导式
squares = {x: x**2 for x in range(6)}
print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 带条件
evens = {x: x**2 for x in range(10) if x % 2 == 0}
print(evens) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
# 交换键值
original = {"a": 1, "b": 2, "c": 3}
swapped = {v: k for k, v in original.items()}
print(swapped) # {1: 'a', 2: 'b', 3: 'c'}
# 从两个列表创建字典
keys = ["a", "b", "c"]
values = [1, 2, 3]
d = {k: v for k, v in zip(keys, values)}
print(d) # {'a': 1, 'b': 2, 'c': 3}4.2 集合推导式
# 基本集合推导式
s = {x**2 for x in range(10)}
print(s) # {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}
# 带条件
evens = {x for x in range(20) if x % 2 == 0}
print(evens) # {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}
# 去重(从列表提取不重复元素)
items = [1, 2, 2, 3, 3, 3, 4]
unique = {x for x in items}
print(unique) # {1, 2, 3, 4}五、哈希原理简述
字典和集合的键必须是**可哈希(hashable)**的对象。可哈希对象的特点:
- 不可变(immutable)
- 有固定的哈希值(通过
hash()函数计算)
# 可哈希的对象(可做字典键)
print(hash("hello")) # 字符串可哈希
print(hash(42)) # 整数可哈希
print(hash((1, 2, 3))) # 元组可哈希
# 不可哈希的对象(不能做字典键)
# hash([1, 2, 3]) # TypeError: 列表不可哈希
# hash({"a": 1}) # TypeError: 字典不可哈希
# 检查是否可哈希
from collections.abc import Hashable
print(isinstance("hello", Hashable)) # True
print(isinstance([1, 2], Hashable)) # False六、综合示例
"""
词频统计程序
"""
text = """
Python is great and Python is easy.
Learning Python is fun and Python is powerful.
"""
# 清洗并分词
words = text.lower().replace(".", "").replace(",", "").split()
# 统计词频
frequency = {}
for word in words:
frequency[word] = frequency.get(word, 0) + 1
# 使用字典推导式
# frequency = {word: words.count(word) for word in set(words)}
print("词频统计:")
print("-" * 30)
for word, count in sorted(frequency.items(), key=lambda x: x[1], reverse=True):
print(f"{word:<12} {count:>3} 次")
# 找出只出现一次的单词
unique_words = {word for word, count in frequency.items() if count == 1}
print(f"\n只出现一次的单词: {unique_words}")
# 找出最常见的词
most_common = max(frequency.items(), key=lambda x: x[1])
print(f"最常见的词: '{most_common[0]}' 出现了 {most_common[1]} 次")小结
- 字典存储键值对,键必须可哈希且唯一,值可以是任意类型
get()、setdefault()、update()是字典的常用方法- 集合无序不重复,支持并集、交集、差集等数学运算
- 字典推导式和集合推导式语法与列表推导式类似
frozenset是不可变集合,可作为字典键- 可哈希对象必须是不可变的(字符串、数字、元组等)
练习
- 有一个字符串
"hello world hello python",统计每个单词出现的次数。 - 两个列表
a = [1, 2, 3, 4, 5]和b = [4, 5, 6, 7, 8],找出它们的共同元素和各自独有的元素。 - 编写程序,删除字典中值为
None或空字符串的键值对。 - 使用集合推导式从一段文本中提取所有不重复的字母(忽略大小写和标点)。
- 有一个嵌套字典表示的菜单,编写函数按价格从低到高打印所有菜品。