当前位置:   article > 正文

【Python基础】从__hash__语法深入理解Python中的哈希 hash_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))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
'
运行

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

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

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

e3 = EntityType(3, 'c')
e4 = EntityType(3, 'c')
if e3 == e4:
    print('Same')
else:
    print('Different')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

输出:

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没有关系。

参考感谢
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/812101

推荐阅读
相关标签