python - 普通类的哈希函数是什么?为什么数据类没有相同的哈希函数?

标签 python numpy python-dataclasses

下面是一个示例,其中数据类“无法”进行哈希处理,但普通类确实可以生成良好的哈希值。

既然普通类也有 np.ndarray 并且应该是不可散列的,为什么这个可以工作?

import numpy as np
from dataclasses import dataclass

class X:
    def __init__(self):
        x = np.ndarray([0,1,1,0,110]) 

@dataclass(frozen=True, eq=True)
class Y:
    name: str
    unit_price: np.ndarray 

a = X()
print(a.__hash__()) 

b = Y(10, np.array([0,1,2]))
print(b.__hash__())

输出:

8787234869218
Traceback (most recent call last):
  File "t.py", line 37, in <module>
    print(b.__hash__())
  File "<string>", line 3, in __hash__
TypeError: unhashable type: 'numpy.ndarray'

最佳答案

因为你使用了:

@dataclass(frozen=True, eq=True)

这里的规则在docs中有描述。 :

If eq and frozen are both true, by default dataclass() will generate a __hash__() method for you. If eq is true and frozen is false, __hash__() will be set to None, marking it unhashable (which it is, since it is mutable). If eq is false, __hash__() will be left untouched meaning the __hash__() method of the superclass will be used (if the superclass is object, this means it will fall back to id-based hashing).

数据类生成了一个哈希函数,该函数基于属性进行哈希处理。当然,它实际上不起作用,因为您使用了 numpy.ndarray

默认情况下,用户定义的对象继承object.__hash__,它只是根据身份进行散列,几乎返回id(self)(尽管不完全是)。

在第一种情况下,两者的行为不会相同,因为您告诉数据类代码生成器使用相应的 __eq__ 创建一个“不可变”类型,该类型基于目的。当然,散列与__eq__一致并且基于属性的值。在第二种情况下,哈希(和相等)基于对象的身份

为了说明这些差异:

>>> from dataclasses import dataclass
>>> @dataclass(frozen=True, eq=True)
... class Point1:
...     x: int
...     y: int
...
>>> points = set()
>>> points.add(Point1(0, 0))
>>> Point1(0, 0) in points
True

所以请注意,集合中有一个具有相同值的不同点对象

但是,以下是基于身份的哈希/相等的运作方式:

>>> class Point2:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
>>> p = Point2(0, 0)
>>> points = set()
>>> points.add(p)
>>> Point2(0, 0) in points
False
>>> p in points
True

关于python - 普通类的哈希函数是什么?为什么数据类没有相同的哈希函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71059306/

相关文章:

python - 在 'with' 语句中返回危险吗?

Python 将分布拟合为钟形曲线

python - 从 pandas DataFrame 转换为原始 numpy 数组可以提高 ML 性能吗?

python - 如何确定数据类中的字段是否具有默认值或是否已显式设置?

python - 如何忽略传递给数据类的额外参数?

python - Numpy fft 结果出乎意料

python - itertools.islice 与列表切片相比

python - 每次在 Python 中运行代码时,如何以相同的顺序随机化 pandas 列?

python - mypy:返回值类型不兼容

python - Python 中的就地快速排序