Python __hash__ 继承

- Python

最近写作业的时候踩上了一个 Python 的坑:

如果父类实现了 __hash__ 方法,而子类重写了 __eq__ 方法,为了保证 hash 和 eq 的语义一致,子类不会隐式继承父类的 __hash__ 方法。如果需要子类的 __hash__ 方法调用父类的实现,则需要手动声明。

文档原文:

A class that overrides __eq__() and does not define __hash__() will have its __hash__() implicitly set to None.

If a class that overrides __eq__() needs to retain the implementation of __hash__() from a parent class, the interpreter must be told this explicitly by setting __hash__ = <ParentClass>.__hash__.

以下为一个示例:

Original Modified
class Parent:
    def __hash__(self):
        return 1

class Child(Parent):
    def __eq__(self, other):
        return True

    # No __hash__ defined



if __name__ == '__main__':
    child = Child()

    # gives error
    print(child.__hash__())
class Parent:
    def __hash__(self):
        return 1

class Child(Parent):
    def __eq__(self, other):
        return True
    
    # NOTE: Added hash
    __hash__ = Parent.__hash__


if __name__ == '__main__':
    child = Child()

    # now it works
    print(child.__hash__())
Traceback (most recent call last):
  File "scratch.py", line 17, in <module>
    print(child.__hash__())
TypeError: 'NoneType' object is not callable
1

相关链接: