Python字典详解(为什么字典查询这么快)

散列表其实是一个稀疏数组(总有空白元素的数组称为稀疏数组)

散列表的单元通常叫做表元(bucket)

在dict的散列表当中每个键值对占用一个表元, 每个表元有两个结构 一个是key 一个是value 

因为表元的大小一致 所以可以通过偏移量来读取某个表元

python会保证当前散列表余有三分之一值 当快达到这个阈值的时候 原有的散列表会copy到一个更大的空间去

如果要把一个对象放到散列值当中 首先需要计算这个对象的散列值 Python内置函数hash()可以做到这点

散列必须胜任索引这个位置,所以 越相近但不相等的值差别越大..  我曾经看过一本书上写的.

1.0001与1.0002 在32位二进制中有20处不同

我们在使用dict时候,若输入不存在的key会抛弃异常. 这源自他的散列算法

为了计算dict[mykey] 会最先调用hash(search_key)的方法来计算[mykey]的散列值

把最低的几位数字当做偏移值 寻找表元(具体几位看散列的大小)如果找到表元是空的就抛出异常

这也是我们若输入不存在的key会报错的原因
若不为空 表单里会有一对found_keys:found_value 这时候会校验 mykey == found_key 若一致就return

若不匹配这个时候就是散列冲突了. 之前我有提到把最低的几位数字当做偏移量.. 这个时候会再度取之上的几位数字继续匹配

若空还是异常 存在返回表元里的value  这里要提到的事返回的事found_value

至于增加与更改的算法与上面相同不同的是

python会先寻找有没有这个key如果有. 就更改不更改就新增不会抛出异常

因为散列算法的原因 dict增加和更改可以直接这么写 mydict[add_key] or mydict[chan_key]

另外在新增值时候.. dict也和list一样会先考虑当前的空间是否足够 也会和list一样check一下 是否需要更换空间

但是我并不知道他会怎么扩容 list是原有的50倍 dict不知道

当dict越大时候 他的散列值所占的位数和索引所占的位置会越大. 这样做的是避免散列冲突

这样看起来可能非常慢 散列冲突也非常多..

但其实是... 你有上百万数据, dict的搜索依旧可以控制在1秒之内. 就算是运气再差散列冲突也可以控制在一只手之内

因为散列冲突所以dict也是无序的

dict带来的优势和限制

支持hash() 并且hash得到的值是不可变的

支持__eq__()方法

如果你自己定于一个class 里面实现了__eq__()方法那么必须对应一个__hash__()而且用的时候一定要慎重

字典在开销上是巨大的. 因为他的散列必须是稀疏的.这导致他在开销上耗费巨大.

假如你有耗费数量巨大的内存, 我建议你存储到元组与list上,最好不要直接用json直接存储

dict的实现是典型用空间换时间 假如你有千万数据. 插叙速度也是不到秒级 每秒能进行200万个key查询.. 这200W个key是建立在散列 算法之上的

当然每个数据结构都要根据你自己的需求作为抉择的考虑 如果你计算机很好. 你就要客户的舒适感. 那么dict肯定是你的首选

又或者说.你计算机很差... 那tuple是你的首选
 

 

你可能感兴趣的:(算法,Python)