Python 数据结构核心:Dict 与 Set 完全指南

3 阅读4分钟

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 的特点

特性DictList
查找速度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 就会混乱。

  • ✅ 可哈希:strintfloattuple(元素都不可变时)
  • ❌ 不可哈希:listdictset

四、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
Pythondictset
JavaScriptObject / Map / SetSet
JavaHashMapHashSet

ES6 中 JavaScript 也新增了 MapSet 数据结构,设计理念与 Python 的 Dict 和 Set 一脉相承。


七、总结

知识点核心内容
哈希表key 通过哈希函数计算索引,O(1) 查找
Dict键值对存储,空间换时间
Set无重复元素的集合,底层与 Dict 相同
可哈希类型key 必须不可变(str、int、tuple)
不可变对象调用方法不改变自身(str)
可变对象调用方法直接修改自身(list)

掌握 Dict 和 Set,就掌握了 Python 中最高效的数据查找方式。


如果本文对你有帮助,欢迎点赞、收藏、评论!有任何问题可以在评论区留言讨论。

标签Python 数据结构 字典 集合 哈希表 前端