Python dict实现

Python dict实现

上次写了Java的HashMap实现方式,Java和Python的实现方式是不同的Java用的是拉链法实现的稀疏数组,而Python用的是 开放定址法

1.散列表

散列表其实是一个稀疏数组(总是有空白元素的数组称为稀疏数组),散列表里的单元通常叫作表元(bucket)。在 dict 的散列表当中,每个键值对都占用一个表元,每个表元都有两个部分,一个是对键的引用,另一个是对值的引用。因为所有表元的大小一致,所以可以通过偏移量来读取某个表元。
Python 会设法保证大概还有三分之一的表元是空的,所以在快要达到这个阈值的时候,原有的散列表会被复制到一个更大的空间里面。(防止hash冲突)
如果要把一个对象放入散列表,那么首先要通过hash()计算这个元素键的散列值。

2.Python散列表算法实现

为了获取 my_dict[search_key] 背后的值,Python 首先会调用 hash(search_key)
来计算 search_key 的散列值,把这个值最低的几位数字当作偏移量,在散列表里
查找表元(具体取几位,得看当前散列表的大小)。若找到的表元是空的,则抛出
KeyError 异常。若不是空的,则表元里会有一对 found_key:found_value。这时
候 Python 会检验 search_key == found_key 是否为真,如果它们相等的话,就会
返回 found_value。
如果 search_key 和 found_key 不匹配的话,这种情况称为散列冲突。发生这种情
况是因为,散列表所做的其实是把随机的元素映射到只有几位的数字上,而散列表本
身的索引又只依赖于这个数字的一部分。为了解决散列冲突,算法会在散列值中另外
再取几位,然后用特殊的方法处理一下,把新得到的数字再当作索引来寻找表元。
若这次找到的表元是空的,则同样抛出 KeyError;若非空,或者键匹配,则返回这
个值;或者又发现了散列冲突,则重复以上的步骤。
这里写图片描述

3.Python dict 对键值的要求

(1) 支持 hash() 函数,并且通过 hash() 方法所得到的散列值是不变的。
(2) 支持通过 eq() 方法来检测相等性。
(3) 若 a == b 为真,则 hash(a) == hash(b) 也为真。

如果你实现了一个类的 eq 方法,并且希望它是可散列的,那么它一定要有个恰当的 hash 方法,保证在 a == b 为真的情况下 hash(a) ==hash(b) 也必定为真。否则就会破坏恒定的散列表算法,导致由这些对象所组成的字典和集合完全失去可靠性,这个后果是非常可怕的。

此篇博客是阅读 流畅的Python 第3.9节,dict和set的背后 做的笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值