美文网首页我的Python之旅
谈谈__eq__和__hash__

谈谈__eq__和__hash__

作者: resolvewang | 来源:发表于2018-06-03 20:31 被阅读21次

今天刷一道算法题的时候用到了list_a == list_b的判断,==is大家都已经是耳熟能详了,前者是判断值是否相等,后者是判断引用是否相等,在用==操作符进行判断的时候,其实内部调用的是__eq__方法。比如

class Item:
  def __init__(self, val):
      self.val = val
  def __eq__(self, other):
      return self.val == other.val

first = Item('hello')
second = Item('hello)
print(first == second) # True

如果不实现__eq__方法,那么自定义类型会调用默认的__eq__方法, 通过默认方法进行比较的相等条件相当严格,只有自己和自己比才会返回True,表现如下

class Item:
  def __init__(self, val):
      self.val = val

first = Item('hello')
second = Item('hello)
print(first == second) # False

因此,在需要进行自定义类型比较的时候,建议实现__eq__方法。

谈及__eq__方法,就不得不谈__hash__,两者总是一起出现.在Python中,如果自定义类定义了__eq__而未定义__hash__方法的话,那么默认将__hash__方法设置为None。这会有什么潜在问题呢?

Python中的对象分为可变和不可变对象,我们从另一个角度来看,可以分为可哈希对象和不可哈希对象。通俗的说,可哈希对象可以作为字典的键,不可哈希对象无法作为字典的键。有时候,我们使用列表或者自定义对象作为字典的键,或者使用set进行元素去重的时候,会遇到unhashable type: xxx之类的问题,这类问题出现的原因就是字典的键或者集合中的元素类型为不可哈希类型。

那么常见的不可哈希类型有哪些呢?几乎都是一些常见的可变类型,比如列表、集合和字典等,都是不可哈希类型。有时候我们有对元素类型为不可变类型的对象进行去重或者使用它作为字典的key的需求,这个时候又该怎么做呢?

我们可以自定义一个类,来实现__eq____hash__方法达到这个效果,且看下面代码

class It(list):
    def __init__(self, vals):
        self.vals = vals
    def __eq__(self, other):
        return self.vals == other.vals
    def __hash__(self):
        # 注意__hash__需要返回一个整数
        return hash(';'.join(vals))

s = set()
j = It(['a', 'b'])
s.add(j)
print(j in set) # True
k = It(['a', 'b'])
print(k in set) # True

从上面结果我们可以看到k这个实例并未加入s这个集合,但是在判断时返回了True,原因就是jk两者的__hash____eq__运算结果相同

我们改改代码,再看看结果

class It(list):
    def __init__(self, vals):
        self.vals = vals
    def __eq__(self, other):
        # 这里如果用 self == other就会出现无限递归,读者可以思考为什么
        return id(self) == id(other)
    def __hash__(self):
        # 注意__hash__需要返回一个整数
        return hash(';'.join(vals))

s = set()
j = It(['a', 'b'])
s.add(j)
print(j in set) # True
k = It(['a', 'b'])
print(k in set) # False

可以看到在关于通过hash运算判断两个对象是否映射成一个值是需要__hash____eq__方法共同决定的

相关文章

  • 谈谈__eq__和__hash__

    今天刷一道算法题的时候用到了list_a == list_b的判断,==和is大家都已经是耳熟能详了,前者是判断值...

  • Python的__hash__函数和__eq__函数

    Python的__hash__函数和__eq__函数 可哈希的集合(hashed collections),需要集...

  • python中 __hash__(self) 和 __eq__(

    参考link 为什么要用hash(self)和 eq(self) 当定义一个类,并设定这个类是可哈希的集合(has...

  • hashable对象

    一个hashable的对象,必须要满足:__hash__的返回值在整个生命周期中不变如果2个对象的__eq__返回...

  • python中的__eq__()方法和__hash__()函数

    关于 eq 和 hash __hash__实际上是返回一个int值,用来唯一标记这个对象。用户自定义类中,如果你没...

  • python让类支持比较操作

    传统方法 自行定义__lt__、__le__、__gt__、__ge__、__eq__等方法,比较繁琐 使用标准库...

  • 趁月儿还没升起来

    趁月儿还没升起来 来吧,我们谈谈 谈谈夜的黑和黑的夜吧 来吧,我们谈谈 谈谈逝去的容颜 谈谈老去的爱情 谈谈手指的...

  • 和过去谈谈

    这两天总是梦到了过去的某些人,我自觉已经忘记,潜意识却不经意地提醒我那些抛到银河系的垃圾仍然有回收利用的那一刻。...

  • 和自己谈谈

    你有没有试过,在大清早起来的时候,异常感觉孤独倾覆着你的❤。好想只有你一个人如此孤独与没用。 一个人躺在床上,一个...

  • 谈谈“equals”和“==”

    总是遇到 equals 和 == 这类题,之前只知道对于基本数据类型, == 比较的是值,对于引用类型,== 比较...

网友评论

    本文标题:谈谈__eq__和__hash__

    本文链接:https://www.haomeiwen.com/subject/qkkssftx.html