Python __hash__ 继承
- 坑 Python
最近写作业的时候踩上了一个 Python 的坑:
如果父类实现了 __hash__
方法,而子类重写了 __eq__
方法,为了保证 hash 和 eq 的语义一致,子类不会隐式继承父类的 __hash__
方法。如果需要子类的 __hash__
方法调用父类的实现,则需要手动声明。
这个之所以是一个坑,因为在代码中的行为看起来很正常:
- Pycharm 的方法跳转可以定位到父类
__hash__
方法 - inspect.getmro 的父类列表正常
- dir(object) 得到的方法列表中的确含有
__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__
.
具体的实现(基于 CPython)
inherit_slots
函数负责继承 slots Line 5432inherit_slots
在处理比较相关的函数(comparison-related)的时候(Line 5432),会使用overrides_hash
方法检查子类是否有重写__eq__
,__hash__
(Line 5274)overrides_hash
中使用_PyDict_ContainsId
方法先检查__eq__
,再检查__hash__
,如果任一存在则返回 1,否则返回 0- 如果
overrides_hash
返回 1,则认为不能继承父类的__hash__
方法,type->tp_hash
不会被设定
以下为一个示例:
Original | Modified |
---|---|
|
|
|
|
相关链接: