如何让 python 数据类继承 __hash__?

Bri*_*man 11 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)
Run Code Online (Sandbox Code Playgroud)

jua*_*aga 8

原因__hash__被设定为Nonedataclasses试图从脚搬起石头砸自己阻止你。您的第二个类eq=True用于数据类装饰器(这是默认值)。从文档:

以下是管理__hash__()方法隐式创建的规则。请注意,您不能__hash__()在数据类中同时具有显式方法并设置 unsafe_hash=True; 这将导致一个TypeError.

如果 eq 和frozen 都为真,默认情况下 dataclass() 会__hash__()为你生成一个 方法。如果 eq 为真,而frozen 为假,则__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
Run Code Online (Sandbox Code Playgroud)

但是,正如评论中指出的那样,这不是很安全,因为您有一个可变对象,现在可以进行哈希处理__eq__,并且与其继承自的实现不一致Hashable