如何断言类覆盖了默认的__hash__和__eq__方法

3

我正在编写一个Python类装饰器。作为装饰器的一部分,我想断言该类没有使用默认的__eq____hash__方法。我该如何实现?

@identifer # should throw AssertionError
class X(object):
    pass

除了谷歌和文档,我还进行了以下探索:

hasattr(X, '__eq__') # True :(

xeq, oeq = X.__eq__, object.__eq__
xeq is oeq # False :(
xeq == oeq # False :(

'__eq__' in X.__dict__ # False :)?

测试类的__dict__似乎可以工作,但如果类继承自一个超类中的方法,则似乎无法正常工作。因此,我可以遍历继承图以查找这些方法,但我想首先知道是否有更清晰的实现方式。

这是在2.7中,但也希望它能在3.x中工作。


1
另外,您是否知道在Python 2.x中,“object”实际上并没有实现“__eq__”? “object.__eq__”实际上是“object”对象本身的一个实例方法;它被调用于“object == whatever”,而不是“object() == whatever”。 - user2357112
1
另外,您试图解决的实际问题是什么?因为这里提出的解决方案(例如Martijn Pieters的解决方案)可能不适用于您。如果您需要哈希性,还需要检查“__eq__”和“__hash__”是否实际可调用。 - Jonas Schäfer
1
@user2357112:当然,但在Python 3中是这样的,所以如果要跨越两个主要版本工作,你仍然需要测试它。 :-) - Martijn Pieters
@user2357112 澄清了标题。 - Michael Deardeuff
1
@JonasWielicki:如果__eq__不可调用,那么就是一个错误。将None赋值给__hash__是被支持的,以表明对象不可哈希,因此它不必是可调用的 - Martijn Pieters
显示剩余8条评论
1个回答

5

如果需要计算整个类层次结构,您可以使用以下方法:

all('__eq__' not in cls.__dict__ for cls in X.mro() if cls is not object)

只有在MRO中的所有类中都没有__eq__属性时,才会返回True,除了object。这对于旧式Python 2类不起作用,因为它们没有class.mro()方法


太完美了!添加 mro() 部分后更加优美! - Michael Deardeuff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接