在__eq__中检查身份有意义吗?

8 投票
5 回答
696 浏览
提问于 2025-04-16 00:50

在为一个类实现自定义的相等性函数时,首先检查对象是否是同一个实例,这样做有意义吗?举个例子:

def __eq__(self, other):
    return (self is other) or (other criteria)

这样做的好处在于,当比较其他条件可能比较耗时(比如比较一些很长的字符串)时,可以提高效率。

5 个回答

2

当你在一个类里实现自定义的相等性时,你可以自己决定是否先检查对象是否是同一个。这完全取决于你自己。在Python中,决定__eq____ne__对于某个参数返回相同的值也是完全可以的;所以你可以定义相等性,使得身份检查不是一个捷径。

这样做肯定能提高速度,虽然具体提高多少取决于方法的复杂程度。我一般在自定义类里不太在意这个,但我也没有很多对速度要求很高的代码(而且即使有,比较对象也不是最耗时的地方)。

对于我大多数的对象,相等性的方法看起来是这样的:

def __eq__(self, o):
    try:
        return self.x == o.x and self.y == o.y
    except AttributeError:
        return False

我可以很容易地在方法开始时加一个if self is o: return True的检查。

另外,如果你重写了__eq__,记得也要重写__hash__,否则在setdict中会出现奇怪的行为。

7

首先,先检查两个对象是否是同一个对象,这个做法在很多情况下是合理的。特别是在判断相等性的时候,找到一些好的捷径(无论是相等还是不相等)是很重要的,这样你可以尽快得到结果。

但是,另一方面,如果你判断相等性的方法很简单,而且在实际使用中不太可能把一个对象和它自己进行比较,那么这个先检查是否相同的步骤就可能是多余的。

举个例子,如果判断两个对象是否相等只需要比较一两个整数,那么这个方法会比检查它们是否是同一个对象更快。这样,你在比较它们的 id 之前,就能得到答案。而且要记住,如果你先检查了它们的身份,发现它们的 id 不一样(在大多数情况下是这样的),那么你就没有得到任何好处,因为你还得进行完整的相等性检查。

所以,如果完整的相等性检查比较耗时,并且有可能一个对象会和它自己进行比较,那么先检查身份是个不错的主意。


另外一个原因是,默认情况下不进行身份检查是因为,有些情况下,两个身份相同的对象可能会被认为是不相等的,这种情况虽然少见,但也是合理的。例如:

>>> s = float('nan')
>>> s == s
False
3

必要性:不需要

这样做有意义吗:当然,有什么不好呢?

默认情况下并没有进行这样的检查,正如你在这里看到的:

class bad(object):
    def __eq__(self, other):
        return False

x = bad()
print x is x, x==x # True, False

撰写回答