【Python基础】从__hash__语法深入理解Python中的哈希 hash

最近看代码遇到了一些自定义的类中实现了__hash__函数,一直模模糊糊的知道__hash__函数对类的实例做了哈希,使每个对象都有一个唯一值对应。但对于

  1. 自己怎么用
  2. 自己什么时候需要用

这两个问题仍然无法解答,于是就搜罗了一下资料,并与诸君共享。

根据场景来解释

代码来源:https://github.com/lavis-nlp/spert/tree/master/spert(为方便演示进行了简化)。

class EntityType:
    def __init__(self, index, short_name):
        self._index = index
        self._short_name = short_name
        
    def __eq__(self, other):
        if isinstance(other, EntityType):
            return hash(self) == hash(other)
        return False

    def __hash__(self):
        print(f'{self._index} 对应的哈希值:{hash((self._index, self._short_name))}')
        return hash((self._index, self._short_name))

该类是一个关于“实体”的类(实体是什么不重要,就想象成是关于猫的类,猫猫有一个编号和名字)。

代码里不仅实现了__hash__,还实现了__eq__。先暂且记住两个是需要同时实现的。

下面使用这个类声明两个对象,

e3 = EntityType(3, 'c')
e4 = EntityType(3, 'c')
if e3 == e4:
    print('Same')
else:
    print('Different')

输出:

3 对应的哈希值:-4381402341035294393
3 对应的哈希值:-4381402341035294393
Same

在Python中自定义的对象默认是可hash 的,并且默认hash 值是通过id 获得,这个id 指的是存储的地址,但从地址得到的hash 值一般不符合我们的要求,我们更希望是通过对具体数据进行hash ,然后得到hash 值。

所以在上面的例子中, hash了由self._index 和 self._short_name组成的元组,这样的好处是如果有两个对象的值相同,那么可以通过比较hash 值快速判断。而用于判断的函数就是__eq__,这就相当于C++中的操作符重载,__eq__相当于重载了==

综上,可以总结出,我们重写_hash__(记住这里是重写,因为默认是可hash的,所以本身会有该函数)的场景就是,如果我们新创建的类,需要保证值不重复性就可以进行进行重写,另外不要忘记还要重写__eq__函数。

另外:有些文章提到了【可变对象和不可变对象】与【不可哈希和可哈希】的关系,提到了list set dict是可变对象,元素会有增有减,“所以” list set dict是不可hash的,和其中的元素是否可hash没有关系。

参考感谢 🤙

[1] Python 哈希教程
[2] python3自定义类:重写__eq__和__hash__函数
[3] python中的hashable(可哈希的)是什么意思
[4] Python id()
[5] python数据结构(三)set使用和原理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值