魔术方法 __hash__ __eq__

 

__hash__:

内建函数hash()调用的返回值,返回一个整数,如果定义这个方法该类的实例就可hash

class M:
    b=899
    def __init__(self):
        self.hy=44
        pass
    def __hash__(self):
        return 89
    # __hash__=None
    def __eq__(self,other): # ==
        # return self.hy==other.hy
        return True
# m=M()
# print(hash(m))

# print(m.__hash__())
lst=[M(),M()]
print(lst)
s=set(lst)
print(s)
for p in s:
    print(hash(p),p)

 

 

 set去重先进行is判断(内存地址相同,则必定相等),而后利用__eq__进行 == 判断

  

class M:
    b=899
    def __init__(self):
        self.hy=44
        pass
    def __hash__(self):
        return 89
    # __hash__=None
    def __eq__(self,other): # ==
        # return self.hy==other.hy
        return False
v=M()
lst=[v,v]
print(lst)
s=set(lst)
print(s)
for p in s:
    print(hash(p),p)

 

 虽然__eq__return False,但是set先进了is判断,内存地址相同,判定重复

 

def _hash(b): # 取模法,求哈希值,值域为3
    return b%3

print(_hash(4) == _hash(7))

哈希值相同,并不代表是同一对象,但是必须可hash才能放到set中

去重依靠: is 和 __eq__

class N:
    __hash__=None

b={N()}

 

 

__eq__ 对应 == 操作符,判断2个对象是否相等,返回bool

__hash__方法只是返回一个hash值作为set的key,去重,还需要__eq__来判断2个对象是否相等

hash值相等,只是hash冲突,不能说明两个对象是相等的

 

 因此,一般来说提供__hash__方法是为了作为set或dict的key,去重要同时提供__eq__方法

 

可hash对象必须提供__hash__方法,没有提供的话,from collections import Hashable,isinstance(var,Hashable)一定为False

去重要提供__eq__方法

 

list类为什么不可hash?

源码中有一句__hash__=None,也就是如果调用__hash__()相当于None()

所有类都继承于object,而这个类具有__hash__()方法,如果一个类不能被hash,就是把__hash__置为None了

from collections import Hashable

class Coordinate:
    def __init__(self,x,y):
        self.x=x
        self.y=y
    def __hash__(self):
        return hash((self.x,self.y))
    def __eq__(self,other): # object中默认是比较内存地址,故需覆盖object方法
        if self is other:
            return True
        return self.x == other.x and self.y == other.y

p1=Coordinate(5,6)
p2=Coordinate(5,6)
print(hash(p1))
print(hash(p2))
print(p1 is p2)
print(p1==p2)
print(set((p1,p2)))
print(isinstance(p1,Hashable))

 

posted @ 2020-10-05 16:00  ascertain  阅读(238)  评论(0编辑  收藏  举报