python dict hash_【python-dict】dict的使用及实现原理
以下内容是针对:python源码剖析中的第五章——python中Dict对象 的读书笔记(针对书中讲到的内容进行了自己的整理,并且针对部分内容根据自己的需求进行了扩展)
一、Dict的用法
Dict的对象在使用到了所谓的关联关系的时候,就是通过key-value的形式,能够通过key值快速定位到某个value值;
Dict的相关操作如下:
class mydict(object):
def __init__(self):
self.d = {}
def fuzhi(self):
self.d = {'2':23, '3':'34'}
def fuzhi2(self):
self.d[1] = 1
self.d['str'] = 123
self.d['may'] = 234
self.d['may'] = 789
def delkey(self):
del(self.d[1]) #删除key时,key值必须存在于dict中,否则会报出 KeyError
self.d.pop('str')
def bianli(self):
for (k,v) in self.d.items():
print k, v
def getkeysandv(self):
print self.d.keys() #获取当前dict中的所有key值
#获取某个元素值:
print self.d.get('345') #若key不存在,则返回默认返回值None
print self.d.get('123', -1) #若key不存在,则返回自定义的返回值-1
print self.d.get('may') #若key值存在,则返回对应的value
def setkeyexcept(self):
self.d[[1,2,3]] =123 #可变对象不能作为key,会提示:TypeError: unhashable type: 'list' 的类似错误
二、Dict的存储实现原理
python中的dict对象也即PyDictObject对象,因为对搜索的效率要求很高,所以选择了散列表(hash table),因为在最优情况下,散列表能够提供O(1)的搜索效率
因此:这里就能想到在leetcode上面刷的题目中,很多通过list形式可以实现的,为了降低时间复杂度,可以用hash的方式,选择dict对象存储(当然具体问题要具体分析)
散列表的基本思想是:通过一定的函数将需要搜索的键值映射为一个整数,根据这个整数作为索引去访问某片连续的内存区域。用于映射的函数称为映射函数,映射所产生的值称为散列值(hash value)。散列函数对搜索效率有直接的决定性作用。在使用散列函数将不同的值可能映射到相同的散列值,这个时候就需要冲突解决(装载率大于2/3时,冲突的概率就会大大增加)
冲突解决在python中使用的是开放定址法,就是通过一个二次探测函数f,计算下一个位置,一直到找到下一个可用的位置为止,在这个过程中会到达多个位置,这些位置就形成了一个“冲突探测链”,这个冲突探测链在查找某个元素的时候起到重要作用,所以在删除某个位置上的元素,不能直接将这个位置的内容删除,如果删除的话,则导致后续依赖于这个位置的其他值就都无法寻找到了,所以只能进行“伪删除”(通过给元素设置状态,dummy态,表示没有存储具体的值但是还会用到的废弃态)
具体的PyDictObject对象中,会存在每一个元素,元素的定义是:
typedef struct{
Py_ssize_t me_hash;
PyObject *me_key;
PyObject *me_value;
}PyDictEntry;
每一个元素有三种状态,分别是:unused、active、dummy
状态
具体含义
unused
me_key=Null,me_value=Null
active
me_key!=Null,me_value!=Null
dummy
me_key=dummy,me_value=Null
PyDictObject对象的定义:
#define PyDict_MINSIZE 8
typedef struct _dictobject PyDictObject;
struct _dictobject{
PyObject_HEAD
Py_ssize_t ma_fill; //元素个数: active+dummy
Py_ssize_t ma_used; //元素个数: Active
Py_ssize_t ma_mask;
PyDictEntry *ma_table;
PyDictEntry *(*ma_lookup) (PyDictEntry *mp, PyObject *key, long hash);
PyDictEntry ma_smalltable[PyDict_MINSIZE];
}
其中各个字段的含义如下:ma_fill域中维护着从PyDictObject对象创建开始直到现在为止所有曾经及正在处于active态的entry个数;ma_used域中维护着当前正处于Active态的entry个数;ma_smalltable的PyDictEntry的数组,表示的是当创建一个PyDictObject对象的时候,至少创建PyDict_MINISIZE个entry被创建(这个数量在程序中定义是8个,这个数量是经过长期的经验所得来的值);ma_table是指向一块区域的,如果entry的数量不超过8个,那么这个指针就指向了ma_smalltable的地址,如果超过了8个,就需要申请一块大的内存,并且ma_table指向这块大的内存
三、Dict的操作实现原理(包括插入、删除、以及缓冲池等)
首先介绍:PyDictObject对象的元素搜索策略:
有两种搜索策略,分别是lookdict和lookdict_string,lookdict_string就是lookdict在对于PyStringObject进行搜索时的特殊形式,那么通用的搜索策略lookdict的主要逻辑是:
(1)对第一个entry的查找:
a)根据hash值获得entry的索引
b)若entry处于unused态,则搜索结束;若entry所指向的key与搜索的key相同,则搜索成功
c)若当前entry处于dummy态,则设置freeslot(这里的freeslot是可以返回作为下一个立即可用的地址来存储entry)
d)检查Active态的entry,若其key所指向的值与搜索的值相同,则搜索成功
(2)对剩余的探测链中的元素的遍历查找:
a)根据所采用的探测函数,获得探测链上的下一个待检查的entry
b)检查到一个unused态的entry,表明搜索失败:
如果freeslot不为空,则返回freeslot;否则返回unused态的entry
c)检查entry的key与所搜索的key的引用是否相同,相同则搜索成功,返回entry
d)检查entry的key与所搜索的key的值是否相同,相同则搜索成功,返回entry
e)遍历过程中,发现dummy态的entry,且freeslot未设置,则设置freeslot
接下来是:PyDictObject对象的元素插入与删除的策略:
需要首先用到搜索策略,搜索成功,则直接将值进行替换,搜索失败,返回unused态或dummy态的entry,设置key、value和hash值,并且根据目前插入的元素情况进行ma_table的大小的调整(调整的依据就是装载率,根据是否大于2/3来进行调整);删除也是类似,先计算hash值,然后搜索相应的entry,搜索成功,删除entry中维护的元素,将entry从Active态修改为dummy态
在PyDictObject的实现过程中,会用到缓冲池,在PyDictObject对象被销毁的时候,才开始接纳被缓冲的PyDictObject对象,定义的缓冲池可接纳的对象数量是80个,创建新PyDictObject对象的时候,如果缓冲池中有,则可以直接从缓冲池中取出使用
python dict hash_【python-dict】dict的使用及实现原理相关推荐
- python读取字符串的list dict_转:Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结...
1 创建列表2 sample_list = ['a',1,('a','b')]3 4 Python 列表操作5 sample_list = ['a','b',0,1,3]6 7 得到列表中的某一个值8 ...
- 【Python】将字典(dict)转化为Dataframe
[Python]将字典(dict)转化为Dataframe_张欣的博客-CSDN博客_python字典转dataframe dictory = {'a':1,'b':2} df = pd.DataFr ...
- python入门(12)dict
python入门(12)dict Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 举个例 ...
- python使用方法-python中dict使用方法详解
dict的特性 dict是python中的一个可变的数据类型,用{}表示,dict的key必须是不可变的数据类型,而value的数据类型可以任意. 格式:{key:value,key:value,ke ...
- python(1):数据类型/string/list/dict/set等
本系列文章中, python用的idle是spyder或者pycharm, 两者都很好用, spyder 是在anaconda 中的, 自带了很多包可以用, pycharm 只是个编译器, 没有很多包 ...
- dict是python语言的内置对象_Python内置了字典:dict的支持
一.dict函数 如果用dict实现,只需要一个"名字"-"成绩"的对照表,直接根据名字查找成绩,无论这个表有多大,查找速度都不会变慢.用Python写一个di ...
- python 基础 list和 tuple dict和set
list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. classmates = ['Michael', 'Bob', 'Tracy'] 要 ...
- Python内置数据类型之Dict
Dict字典,是另一种可变类型的容器模型,可以存储任意类型对象. 1.字典的创建 字典的每个键值对(key->value)使用冒号(:)分隔,键值对之间使用逗号(,)分隔,使用花括号{}包含元素 ...
- python中ht表示什么_如何看待某国内大公司Python面试题,有关dict中初始化为固定值?...
职业发展 Python 如何看待某国内大公司Python面试题,有关dict中初始化为固定值? 阅读下面的代码,写出A0,A1至A6的最终值. A0 = dict(zip(('a','b','c',' ...
- Python:数据结构(list, tuple, Dict Set)
list: Python中内置的有序数据结构,即数组.由于Python是动态语言,因此数组元素的类型没有限定. classmates = ["Michael", "Dav ...
最新文章
- pytorch IntermediateLayerGetter
- mysql查询数据教程_MySQL 查询数据
- 一个PHP程序的“怪问题”
- G.Fast应用将开启 中国光进铜退没白干
- 一步步学习微软InfoPath2010和SP2010--第四章节--处理SP列表表单(6)--列表表单的局限...
- 2007武汉.NET俱乐部沙龙-VS2008、WPF、Silverlight
- C++算法五:二分查找(折半)查找
- windows 安装PyAudio库
- 基于JAVA+SpringBoot+Mybatis+MYSQL的物业管理系统
- ASP.NET - 一般处理程序获取session值
- html 怎么设置时间函数,JavaScript日期函数 - 计时器、innerHTML
- 如何查看局域网内所有的IP
- 中职计算机基础知识总结,中职计算机基础知识整理
- 【人工智能项目】深度学习实现图像多标签分类
- Accidental override: The following declarations have the same JVM signature (getWindow()Landroid/vie
- Spring JMX注解的使用方式:@ManagedResource @ManagedOperation @ManagedAttribute
- vue引入 wps在线编辑版,可进行 预览,编辑, 打印等功能。
- UTON NFT的到来将为摄影师带来全新的未来!
- 7.前端入门小工具之PS辅助
- Android辅助权限实战之微信自动评论与点赞
热门文章
- ipconfig命令指南
- fstream下的读写操作
- c语言如何把变量按位颠倒,求答案,用C语言编程,用户输入一个正整数,把他的各位数字前后颠倒,并输入点到后的结果...
- php显示html表单内容,HTML表单是什么?HTML表单内容的详细介绍(附代码)
- linux+基因组字符替换,liftover基因组版本直接的coordinate转换
- eslint vscode 自动格式化_使用 VSCode 的必备三大神器,这才是开发 Vue 的真香解决方案...
- threadlocal存连接对象的目的_终于懂了ThreadLocal,不再害怕面试官问了
- Win7电脑设置定时关机的操作方法
- xp电脑怎么取消开机密码
- Java面向对象编程篇4——内部类