让__eq__引发异常的陷阱?

时间:2015-10-29 13:35:34

标签: python equality

我有一种平等比较没有意义的类型。为引用或值相等显式比较此类型的两个实例将指示调用代码中的逻辑错误。

定义__eq__引发异常是不是很糟糕?这有什么陷阱吗?它被隐含地称为某些常见操作的一部分吗?

在像Haskell这样的语言中,我不会实现Equal类型类,并且尝试比较将是编译错误。由于python是完全动态的,如果这个定义不是一个好主意,我是否有一个选项可以帮助鼓励正确使用?

我可以return NotImplemented,但如果RHS也返回NotImplemented,那么它会进行后退比较,最终会导致身份比较,而我仍然不想要这样做。

1 个答案:

答案 0 :(得分:2)

使__eq__抛出将阻止您的类被用作字典中的键。字典是将任意值“附加”到引用可比较对象的常用方法。

例如:

class NotComparableAtAll:
    def __eq__(self, other):
        raise ValueError ('haha')

cache = { }
x, y = NotComparableAtAll (), NotComparableAtAll ()

cache[x] = 1
cache[y] = 2

此操作失败,说该类型不可清除。

但是,如果您确实将__hash__添加到了类中(默认情况下,只要您定义__eq__就会删除),示例就会出现,几乎所有时间都能正常工作,只有当两个不同的对象在某台机器上具有相同的散列时,它才会无法预料地失败。要重现它,请将__hash__定义为始终返回0(符合__hash__要求)。

此外,覆盖__eq__会破坏一些标准函数,通过引用进行比较会很有用:

my_list = [x, y]
my_list.remove (y)

这当然可以被认为是“这些对象必须真的不能被比较”的另一种情况,但我想可以提出其他类似的例子,其中比较以某种方式嵌套在不同的有用操作中。