Featured image of post Dict和set

Dict和set

dict

Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。

1
2
3
d = {'Michael:95,'BOb':75,'Tracy':85}
d['Michael']
95

为什么dict查找速度这么快?因为dict的实现原理和查字典是一样的。假设字典包含了1万个汉字,我们要查某一个字,一个办法是把字典从第一页往后翻,直到找到我们想要的字为止,这种方法就是在list中查找元素的方法,list越大,查找越慢。

第二种方法是先在字典的索引表里(比如部首表)查这个字对应的页码,然后直接翻到该页,找到这个字。无论找哪个字,这种查找速度都非常快,不会随着字典大小的增加而变慢。

dict就是第二种实现方式,给定一个名字,比如'Michael',dict在内部就可以直接计算出Michael对应的存放成绩的“页码”,也就是95这个数字存放的内存地址,直接取出来,所以速度非常快。

把数据放入dict的方法,除了初始化时指定外,还可以通过key放入:

1
2
3
d['Adam'] = 67
print(d['Adma'])
67

由于一个key只能对应一个value,所以,多次对一个key放入value,后面的值会把前面的值冲掉:

1
2
d = ['jack'] = 90 
print(d['jack'])

通过in判断key是否存在

1
2
'Thomas' in d
false

二是通过dict提供的get()方法,如果key不存在,可以返回None,或者自己指定的value:

1
2
3
d.get('Thomas')
d.get('Thomas',-1)
-1

要删除一个key,用pop(key)方法,对应的value也会从dict中删除:

1
2
3
4
d.pop('BOb')
75
print(d)
{'Michael': 95, 'Tracy': 85}    

dict内部存放的顺序和key放入的顺序是没有关系的。

和list比较,dict有以下几个特点:

  1. 查找和插入的速度极快,不会随着key的增加而变慢;
  2. 需要占用大量的内存,内存浪费多。

而list相反:

  1. 查找和插入的时间随着元素的增加而增加;
  2. 占用空间小,浪费内存很少。

dict是用空间来换取时间的一种方法

第一条就是dict的key必须是不可变对象

set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key

1
2
3
s = {1,2,3}
print(s)
{1,2,3}

通过add(key)方法可以添加元素到set中,可以重复添加,但不会有效果

1
2
3
4
5
6
s.add(4)
print(S)
{1,2,3,4}
s.add(4)
print(s)
{1,2,3,4}

通过remove(key)方法可以删除元素

注:无法使用s.pop

1
2
3
s.remove(4)
s
{1,2,3}

set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作:

1
2
3
4
5
6
s1 = {1,2,3}
s2 = {2,3,4}
s1 & s2 
{2,3}
s1|s2
{1,2,3,4}

set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象,因为无法判断两个可变对象是否相等

为了保证 dict 和 set 能快速、准确地找到数据,它们要求钥匙(key)必须是绝对不可变**的 。

整理了关于 dict 和 set 的详细对比及操作表格:

1. dict 与 set 的核心概念对比

这两者在 Python 中都是非常高效的数据结构,但用途有所不同:

特性dict (字典)set (集合)
定义使用 键-值 (key-value) 存储,具有极快的查找速度 [1]。一组 key 的集合,但不存储 value [2]。
重复性一个 key 只能对应一个 value,多次赋值会覆盖旧值 [3]。key 不能重复,重复元素会自动被过滤 [2, 4]。
有序性内部存放顺序和 key 放入的顺序无关 [2]。无序,显示的顺序不代表内部实际顺序 [4]。
对 Key 的要求必须是 不可变对象(如字符串、整数)[2]。同样必须是 不可变对象,不能放入 list 等 [4]。
主要用途快速根据 key 查找对应的 value [1]。数学意义上的去重、交集、并集运算 [4]。

2. dict 与 set 的常用操作方法

下表列出了文中提到的主要操作方式:

操作类型dict (字典)set (集合)
初始化/创建d = {'Michael': 95, 'Bob': 75} [1]s = {1, 2, 3} 或 set([5-7]) [2, 4]
添加/修改d['Adam'] = 67 [3]s.add(4) [4]
查找/判断是否存在key in d 或 d.get(key) [3]key in s (原理同 dict)
删除元素d.pop(key) [3]s.remove(key) [4]
特殊运算——交集 s1 & s2,并集 `s1

3. dict 与 list 的性能对比(空间换时间)

源码中明确对比了 dict(哈希表原理)和 list(顺序查找)的差异 [2]:

特性dictlist
查找和插入速度极快,不会随 key 增加而变慢 [2]。随着元素增加,耗时越来越长 [2]。
内存占用较大,需要占用大量内存,浪费多 [2]。占用空间小,浪费内存很少 [2]。
结论用空间换取时间的方法 [2]。适合数据量小、对内存敏感的场景。

💡 重要提醒:关于“不可变对象”

无论是 dict 的 key 还是 set 的元素,都必须使用 不可变对象 [2, 4]。

  • 可以放入: 字符串 (str)、整数 (int)、全由不可变对象组成的元组 (tuple) [2, 8]。

  • 不可以放入: 列表 (list),因为它是可变的,无法计算固定的哈希值,会导致报错 [2, 4]。

在 Python 中,花括号 {} 和圆括号 () 分别代表了不同的数据结构,其核心区别在于功能用途和可变性:

1. 花括号 {}:用于 dict 和 set

在源码中,花括号主要有两种用途:

  • dict(字典): 采用 “键-值对”(key-value) 的形式存储数据 [1]。
    • 写法: d = {'Michael': 95, 'Bob': 75} [1, 2]。
    • 特点: 查找速度极快,不会随元素增加而变慢,但占用内存较多 [1, 3]。
  • set(集合): 是一组 key 的集合,但不存储 value [3]。
    • 写法: s = {1, 2, 3} [3]。
    • 特点: 元素不重复(自动过滤重复项),且内部元素是无序的 [4]。

2. 圆括号 ():用于 tuple

圆括号在源码中被用来表示 tuple(元组)。

  • tuple(元组): 一种不可变的有序列表 [5]。
    • 写法: t = (1, 2, 3) [5]。
    • 特点: 一旦初始化就不能修改。因为它是不可变的,所以安全性更高 [5]。

3. 核心区别汇总

特性花括号 {} (dict/set)圆括号 () (tuple)
数据类型dict 或 set [1, 3]tuple [5]
存储内容dict 存键值对,set 只存键 [1, 3]存储有序的元素序列 [5]
重复性key 不允许重复(set 会去重)[3, 4]允许元素重复
有序性无序(存放顺序与放入顺序无关)[3, 4]有序 [5]
可变性dict 和 set 本身是可变的(可添加删除)[2, 4]tuple 是不可变对象 [5]
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 Stack 由 Jimmy 设计