Python 数据结构核心:Dict 与 Set 完全指南
深入理解 Python 字典和集合的底层原理与实战用法,掌握哈希表驱动的 O(1) 查找利器。
前言
假设要根据同学的名字查找对应的成绩,不用字典,怎么做?
names = ['张三', '李四', '王五']
scores = [95, 99, 100]
可以用两个列表,一个存名字,一个存成绩,通过下标对应。但这样查找一个名字需要遍历整个列表,时间复杂度 O(n)。
有没有更快的方式?答案就是 Dict(字典)。
一、什么是哈希表(Hash Table)?
哈希表是 Dict 和 Set 的底层实现,理解它就理解了这两个数据结构的核心。
1.1 基本原理
key → 哈希函数(计算) → 索引 → 存储位置 → value
- 哈希表是一种基于键值对存储数据的数据结构
- key 唯一,经过哈希运算得到一个索引
- 索引指向一个存储位置,存储着对应的 value
- 查找时直接根据 key 计算索引,取出 value
1.2 形象理解
就像书本最前面的索引部分——不需要从第一页翻到最后一页,直接根据偏旁或字母定位到页码,O(1) 时间复杂度。
二、Dict 字典详解
2.1 基本操作
# 创建字典
d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
# 通过 key 查找 value
d['Michael'] # 95
# 动态添加 key:value
d['Adam'] = 67
d['Adam'] # 67
# 修改已有 key 的 value
d['Jack'] = 90
d['Jack'] = 88
d['Jack'] # 88
2.2 安全查找
当 key 不存在时,直接用 d['Thomas'] 会抛出 KeyError。更安全的方式:
# 方法一:in 判断
"Thomas" in d # False
# 方法二:get 方法(推荐)
d.get('Thomas') # None
d.get('Thomas', -1) # -1(指定默认值)
d.get('Jack', -1) # 88(key 存在,返回实际值)
2.3 删除元素
d.pop('Bob') # 删除 key 为 'Bob' 的元素,返回对应的 value
2.4 Dict 的特点
| 特性 | Dict | List |
|---|---|---|
| 查找速度 | O(1),极快 | O(n),随元素增加变慢 |
| 插入速度 | O(1),极快 | O(n),随元素增加变慢 |
| 内存占用 | 大,内存消耗多 | 小,浪费内存很少 |
| 是否有序 | Python 3.7+ 保持插入顺序 | 有序 |
核心权衡:Dict 用空间换时间,List 用时间换空间。
三、Key 的限制:可哈希类型
3.1 什么是 unhashable type?
key = [1, 2, 3]
d[key] = 'a list'
# TypeError: unhashable type: 'list'
Dict 的 key 必须是不可变类型(hashable)。
3.2 为什么?
Dict 靠 key 计算出 value 的存储位置。如果 key 可变,每次计算出来的哈希值可能不同,Dict 就会混乱。
- ✅ 可哈希:
str、int、float、tuple(元素都不可变时) - ❌ 不可哈希:
list、dict、set
四、Set 集合详解
4.1 Set 是什么?
Set 和 Dict 类似,也是一组 key 的集合,但不存储 value。由于 key 不能重复,所以 Set 中没有重复元素。
# 创建 Set
s = {1, 2, 3}
s # {1, 2, 3}
# 从列表创建(自动去重)
s = set([1, 2, 3, 2, 5])
s # {1, 2, 3, 5}
4.2 基本操作
# 添加元素
s.add(4)
s # {1, 2, 3, 4, 5}
# 删除元素
s.remove(4)
s # {1, 2, 3, 5}
4.3 集合运算
s1 = {1, 2, 3}
s2 = {2, 3, 4}
s1 & s2 # 交集:{2, 3}
s1 | s2 # 并集:{1, 2, 3, 4}
4.4 Set vs Dict
Set 和 Dict 唯一的区别在于没有存储对应的 value,底层原理完全一样。
五、不可变对象 vs 可变对象
5.1 str 是不可变对象
str = 'abc'
print(str.replace('a', 'A')) # Abc
print(str) # abc(原字符串不变)
replace 作用在字符串对象 'abc' 上,并没有改变 'abc' 的内容,而是返回了一个新的字符串 'Abc'。
5.2 list 是可变对象
a = ['c', 'b', 'a']
print(a.sort()) # None(sort 修改原列表,返回 None)
a # ['a', 'b', 'c'](原列表已改变)
总结:对于不可变对象,调用自身的任意方法也不会改变该对象的内容;对于可变对象,方法会直接修改原对象。
六、与其他语言的对比
| 语言 | 字典/Map | 集合/Set |
|---|---|---|
| Python | dict | set |
| JavaScript | Object / Map / Set | Set |
| Java | HashMap | HashSet |
ES6 中 JavaScript 也新增了 Map 和 Set 数据结构,设计理念与 Python 的 Dict 和 Set 一脉相承。
七、总结
| 知识点 | 核心内容 |
|---|---|
| 哈希表 | key 通过哈希函数计算索引,O(1) 查找 |
| Dict | 键值对存储,空间换时间 |
| Set | 无重复元素的集合,底层与 Dict 相同 |
| 可哈希类型 | key 必须不可变(str、int、tuple) |
| 不可变对象 | 调用方法不改变自身(str) |
| 可变对象 | 调用方法直接修改自身(list) |
掌握 Dict 和 Set,就掌握了 Python 中最高效的数据查找方式。
如果本文对你有帮助,欢迎点赞、收藏、评论!有任何问题可以在评论区留言讨论。
标签:Python 数据结构 字典 集合 哈希表 前端