散列表其实是一个稀疏数组(总有空白元素的数组称为稀疏数组)
散列表的单元通常叫做表元(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是你的首选