【发布时间】:2016-07-28 04:46:54
【问题描述】:
阅读this answer 似乎,如果__eq__ 在自定义类中定义,__hash__ 也需要定义。这是可以理解的。
但是不清楚,为什么 - 实际上 - __eq__ 应该与 self.__hash__()==other.__hash__ 相同
想象这样一个类:
class Foo:
...
self.Name
self.Value
...
def __eq__(self,other):
return self.Value==other.Value
...
def __hash__(self):
return id(self.Name)
这种方式可以按值比较类实例,这可能是唯一合理的用途,但在名称上被认为是相同的。
这样set 不能包含多个具有相同名称的实例,但比较仍然有效。
这样的定义可能有什么问题?
之所以用Value定义__eq__、__lt__等,是为了能够通过Value对实例进行排序,并且能够使用max等函数。例如,他的类应该代表设备的物理输出(比如加热元件)。这些输出中的每一个都有唯一的名称。值是输出设备的功率。要找到要打开的加热元件的最佳组合,能够通过功率(值)比较它们是很有用的。但是,在集合或字典中,不可能有多个具有相同名称的输出。当然,不同名称的不同输出可能很容易具有相同的功率。
【问题讨论】:
-
如果
Value对平等很重要,您通常会将__hash__实现为return hash(self.Value)。 -
在这种情况下,值不足以表示身份,仅表示大小。通过值定义它 _eq 以及 lt 和其他是允许类按值排序的方法,但具有相同值的实例不被认为是相同的。
-
你能举一个不那么抽象的例子吗?目前的问题似乎是你的类没有一致地定义。
-
我用具体的例子更新了这个问题,希望它更清楚。
-
在你的情况下,我建议平等将纯粹是在价值和散列上的名称和价值(
return hash(self.Name) ^ hash(self.Value)。“相等的对象需要散列相同” 是稍微简化一下,相同的对象应该散列相同。
标签: python class hash equivalence