以下内容将起作用,但我不想在每个子类中重复__hash__
。有没有办法告诉数据类继承哈希函数(即不将其设置为None
)?
from dataclasses import dataclass
@dataclass
class Hashable:
def __hash__(self):
hashed = hash((
getattr(self, key)
for key in self.__annotations__
))
return hashed
@dataclass
class Node(Hashable):
name: str = 'Undefined'
def __hash__(self):
return Hashable.__hash__(self)
答案 0 :(得分:2)
您的__hash__
被设置为None
的原因是dataclasses
试图阻止您用脚射击自己。您的第二个类具有eq=True
作为数据类装饰器(这是默认值)。从文档中:
以下是管理
__hash__()
方法的隐式创建的规则。 请注意,您不能同时拥有显式的__hash__()
方法 数据类并设置unsafe_hash = True;这将导致TypeError
。如果eq和Frozen均为true,则默认情况下dataclass()将生成一个
__hash__()
方法适合您。 如果eq为true,frozen为false,则__hash __()将设置为None,将其标记为不可散列(因为它是可变的,因此它是不可散列的)。如果eq为false,则__hash__()
将被留下 保持不变,表示将使用超类的__hash__()
方法 (如果超类为object
,则意味着它将退回到基于id的位置 哈希)。
因此只需传递eq=False
:
In [1]: from dataclasses import dataclass
...:
...:
...: @dataclass
...: class Hashable:
...:
...: def __hash__(self):
...: hashed = hash((
...: getattr(self, key)
...: for key in self.__annotations__
...: ))
...: return hashed
...:
...:
...: @dataclass(eq=False)
...: class Node(Hashable):
...: name: str = 'Undefined'
...:
In [2]: hash(Node())
Out[2]: -9223372036579626267
但是,正如注释中所指出的那样,这不是很安全,因为您有一个可变对象,该对象现在可以进行哈希处理,并且与__eq__
的实现不一致,它是从继承而来的Hashable