栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

python dict类型底层实现原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python dict类型底层实现原理

数据结构 HashMap

dict 其实叫做字典是属于直译了
我个人比较喜欢叫他hashmap
因为在不同的编程语言中,数据结构都是大同小异的,迁移到其他编程语言的数据结构,这个结构就叫hashmap

写一段python的伪代码

dict[key] = value;

在python中 字典的keyvalue叫做键值对,

hashmap[hash] = value;

在数据结构hashmap中是以hash值作为键的

其实dict的底层也是给变量存了一个hash值,默认是这个变量的id(也就是地址)

__hash__和__eq__的区别

对于一个自定义的Position类
我们可以重载==运算符,令两个x和y都相等的Position类,在执行equal的时候返回True。

def __eq__(self, other):
	return self.x == other.x and 
		self.y == other.y;
def __hash__(self, other): #如果只重载__eq__的话,baseObject类会认为__hash__不需要继承,导致没有__hash__函数
	return id(self);

但是在hashmap这个结构里,如果想把两个重载了equal的Position类作为相同键值,
要符合hashmap的要求,hashmap数据结构里必须要保证两个equal相等的值,它们的hash也要一样。
hashmap需要比较的第一步是__hash__,而真正存入hashmap键值的是数据结构的地址。

所以hashmap会先去比较两个数据结构的hash,如果两个数据结构的hash是不一样的,那么就认为这两个数据结构是不可能相等的。

想让他们的hash值相同,那么我们最好借用系统给的hash函数,给其中hashable的数据做一个hash,作为我们自定义数据结构的hash。

我们把x和y值变成一个tuple,对他做hash,把这个hash值作为我们自定义object的hash。

def __eq__(self, other):
	return self.x == other.x and 
		self.y == other.y;
def __hash__(self, other): #如果只重载__eq__的话,baseObject类会认为__hash__不需要继承,导致没有__hash__函数
	return hash((self.x, self.y));

如果把__eq__重载去掉,那么又会变成两个key值,因为根据hashtable的原理,两个不同的数据结构有可能拥有相同的hash,这个叫hash collision(哈希冲突),在比较完hash之后一定还要比较这两个数据是不是一样的。

哈希冲突:举个例子

如果对于字符串的hash函数是加和运算
an 的ascii码 97 + 110
和cl 的ascii码 99 + 108是相等的
就会产生hash冲突,就像MD5一样,hash值只能代表原始数据的部分特征,对于高精度的运算,还是需要进行精确的比较。

不重载__eq__的话,自定义数据结构会去比较他们的id是不是一样的。

C层面的比较

hashmap在最开始,还进行了一段C层面的比较,优先比较新的key和原来hash相同位置的key是不是相等的。
这个层面比较的实际上是这两个数据结构实例在C中对应的指针。
所以两个地址相同的key,无论__hash__、__eq__是否相等,最后一定代表的是同一个键。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/755120.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号