让 __eq__ 引发异常的陷阱?

Dae*_*yth 5 python equality

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

__eq__定义引发异常是不是不好?这其中有陷阱吗?它是否作为某些常见操作的一部分隐式调用?

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

我可以return NotImplemented,但是如果 RHS 也返回,它会进行后备比较,最终会导致身份比较NotImplemented,但我仍然不希望这样。

小智 4

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

例如:

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

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

cache[x] = 1
cache[y] = 2
Run Code Online (Sandbox Code Playgroud)

这失败了,说明该类型不可散列。

但是,如果您确实添加__hash__到类中(定义后默认值就会被删除__eq__),该示例似乎几乎一直工作正常,只是如果两个不同的对象在某些机器上具有相同的哈希值,它可能会不可预测地失败。要重现它,请定义__hash__为始终返回 0(这确实符合__hash__要求)。

此外,__eq__像这样的重写会破坏一些标准函数,在这些函数中通过引用进行比较会很有用:

my_list = [x, y]
my_list.remove (y)
Run Code Online (Sandbox Code Playgroud)

这当然可以被视为“这些对象确实不能进行比较”的另一种情况,但我想人们可以想出其他类似的例子,其中比较以某种方式嵌套在不同的有用操作中。