我在这里看到的问题是您正在使用两种不同的平等概念。如果我正确理解了您的评论,则您已被覆盖__eq__
以返回将两个参数组合到==
. 如果所述表达式的计算结果为 True(在某种意义上),那么这两个表达式相等;并且如果您的表达式类也以返回iff 表达式为真的方式实现__nonzero__
(__bool__
在 Python 3 中),那么从表面上看,这似乎应该可以正常工作。__nonzero__
True
但事实上,在我看来,您定义的平等概念与 Python 中正常的平等概念相比,是一个非常不同的平等概念。哈希性的一个基本要求是,如果两个项目评估为相等,那么它们应该是完全可互换的。虽然您的两个表达式对象可能评估为“相等”,但我不确定它们是否可以互换!毕竟,5 + 5
并且8 + 2
评估到相同的结果,但它们并不相同,是吗?鉴于这两个表达式,我怀疑很多人会期望它们在字典中散列到两个单独的 bin 中!
然而,如果不给出__eq__
更传统的定义,这种行为将是困难的。正如文档所说,“比较相等的可散列对象必须具有相同的散列值。” 因此,如果这么__eq__
说5 + 5
并且8 + 2
相等,那么它们必须散列到相同的值。这意味着要使您的表达式像现在一样可散列,您必须选择一个__hash__
能够为所有计算为 equal 的表达式确定规范形式的表达式。这对我来说听起来很难。
简而言之,如果这些表达式是不可变的,并且如果您重新定义__eq__
以返回True
iff 表达式相同(比“等于”更强的要求),那么使它们可散列应该没有问题。另一方面,我认为不可散列的不可变类型没有任何问题。而且我不建议在不重新定义__eq__
.
所以这一切都归结为你想以__eq__
一种非常规的方式定义有多糟糕。我想总的来说,我会使用 的传统定义__eq__
,只是为了避免产生意外行为。毕竟,特殊情况还不足以打破规则。