python字典

python3.6字典类型的改变

python3.6之前的版本,字典是无序的,要使用有序字典则需要调用orderdict对象。3.6之后字典就默认为有序字典。原因如下:

1.python3.6之前的版本:

# 在python中新建一个字典
new_dict = {}

这里Cpython定义的是:新建了一个8X3的空二维数组的内存空间存储hash函数返回值,key的内存地址,value的内存地址。

例如:

new_dict = {}
# 这里就新建了一个8X3的空二维数组
# 实行添加操作
new_dict['name'] = 'zhangsan'
print(hash('name'))
"""
>>-6364352962320531015
hash('name') % 8 = 5
这里的字典内存变成了
[[_,_,_],
[_,_,_],
[_,_,_],
[_,_,_],
[_,_,_],
[-6364352962320531015,指向'name'的指针,指向'zhangsan'的指针],
[_,_,_],
[_,_,_],]
"""

使用hash函数取得的值对8取余,就是该key:value在内存数组中的下标位置。对应的是指向key和value的内存指针。

这里注意python自带的hash函数,每次运行得到的值都不同

>>> new_dict = {}
>>> new_dict['name'] = 'zhangsan'
>>> a = hash('name')
>>> print(a)
-389504538906009921
# 退出本次运行之后再次运行
>>> new_dict = {}
>>> new_dict['name'] = 'zhangsan'
>>> a = hash('name')
>>> print(a)
5913736675476427286

当两个key值的hash函数值取余相等时,这里的hash表存储模式采用开放寻址法。

hash表开放寻址法

hash表:一种使用key记录value内存地址的数据结构。

设字典二维数组的第一个值为hash标签。

则使用散列函数来生成标签,token = hash(key) + di,插入位置 = token/m ,m为哈希表长,这里暂时为8

当di = 1,2,3,…,m-1,称线性探测再散列;

di = 12,-12,22,-22,⑶2,…,±(k)2,(k<=m/2)称二次探测再散列;

di = 伪随机数序列,称伪随机探测再散列。

所以这里当取余相同时,需要操作di继续寻找其他空余位置。当字典的键值对数量超过当前数组长度的2/3时,数组会进行扩容,8行变成16行,16行变成32行。长度变了以后,原来的余数位置也会发生变化,此时就需要移动原来位置的数据,导致插入效率变低。

这里可以对比一下python中的列表删除操作:

a = [1,2,3,4,5]
for i in a:
    if i > 2:
        a.remove(i)
print(a)
>>>[1,2,4]

这里4没有删掉的原因就是,在删除下标为2的3后,下一个应该删除下标为3的数据,这时列表的长度变成了3,位置和下标都进行了变化,所以删除的是5而不是4。

2.python3.6之后

同样进行新建字典操作:

new_dict = {}
# 这里底层与之前不同的是新建了两个数组
# 一个一维数组,一个空二维数组
# indices = [none,none,none,none,none,none,none,none]
# entries = []
new_dict['name'] = 'zhangsan'
a = hash('name')
print(a)
>>> 1329151475607574641
>>> a % 8 = 1
# indices >>> [none,0,none,none,none,none,none,none]
# entries >>> [[1329151475607574640,'name','zhangsan']]

indices下标集作用,将entries中的位置信息存储在indices的取余结果位置

查找顺序:

​ hash(key) % 8 → index

​ entries[indices[index]] → 对应数据

这样设置,每次添加新的数据entries就会在末尾自动顺序添加, 遍历的时候也只需要遍历enties就行。

优势:1.当数据量少于8组时,以前的字典因为事先开辟了一个至少8X3的二维数组空间而会导致内存浪费。

​ 2.以前遍历字典因为字典的二维数组空间可能为空,所以每次都要全部循环一遍而且需要判断是否为空,新版字典只需要顺序遍历一遍enties列表就行,时间复杂度大大减少。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值