映射(mapping)结构,基于哈希表存储键值对数据
key必须是可哈希类型
哈希冲突时,采用开放寻址法
散列表是一个稀疏数组。1/3表元为空,因此空间效率低
散列表里元素通常叫做表元(bucket)
内置类型 hash()
自定义类型,重写__hash__。
两个对象相等,那么散列值必须相等。
自定义类型,重写__eq__
散列值保证索引空间中分散:
理想情况下,越相似,它们的散列值差别越是大
获得my_dict[search_key]
1)调用hash(search_key)来计算search_key的散列值
2)把这个值最低的几位数字当做偏移量,在散列表中查找表元(几位,根据散列表大小)
3)若找到表元为空,则KeyError
4)若表元不为空,表元里面有一对found_key:found_value
5)如果search_key = found_key 为True,返回found_value
如果为False,称为散列冲突
操作 | 时间复杂度 |
---|---|
copy | O(n) |
get(value) | O(1) |
set(value) | O(1) |
delete(value) | O(1) |
search(in) | O(1) |
iterration | O(n) |
一个可散列的对象必须满足以下要求:
(1) 支持 hash() 函数,并且通过 hash() 方法所得到的散列 值是不变的。
(2) 支持通过 eq() 方法来检测相等性。 (3) 若 a == b 为真,则 hash(a) == hash(b) 也为真。
所有由用户自定义的对象默认都是可散列的,因为它们的散列值由 id() 来获取,而且它们都是不相等的。
自定义类型默认实现了__hash__和__eq__
散列表必须稀疏,导致空间的效率低。优化往往和可维护性的对立面
dict的实现是典型的空间换时间:
字典类型有这巨大的内存开销,但它们提供了无视数据量大小的快速访问
当往dict里添加新建而又发生了散列冲突的时候,新建可能被安排存放在另外一个位置。
两个内容相等,顺序不同的,题目是相等
collections.OrderDict,有序字典
无论何时往字典里添加新的键,Python解释器都可能做出字典扩容的决定。
扩容过程中可能会发生新的冲突,导致新散列表中的键的次序发生变化。
想扫描并修改一个字典,最好分为2步:
1:对字典迭代,以得到需要添加的内容,把这些内容放在一个新字典里;
2:迭代结束之后再对原有字典进行更新
在 Python 3 :
.keys()、.items() 和 .values() 方 法返回的都是字典视图。
也就是说,这些方法返回的值更像集 合。
视图还有动态的特性, 它们可以实时反馈字典的变化