如何使python数据类继承__hash__?

时间:2018-12-31 18:14:35

标签: python hash data-class

以下内容将起作用,但我不想在每个子类中重复__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)

1 个答案:

答案 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