在__eq__中检查身份有意义吗?
在为一个类实现自定义的相等性函数时,首先检查对象是否是同一个实例,这样做有意义吗?举个例子:
def __eq__(self, other):
return (self is other) or (other criteria)
这样做的好处在于,当比较其他条件可能比较耗时(比如比较一些很长的字符串)时,可以提高效率。
5 个回答
当你在一个类里实现自定义的相等性时,你可以自己决定是否先检查对象是否是同一个。这完全取决于你自己。在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__
,否则在set
和dict
中会出现奇怪的行为。
首先,先检查两个对象是否是同一个对象,这个做法在很多情况下是合理的。特别是在判断相等性的时候,找到一些好的捷径(无论是相等还是不相等)是很重要的,这样你可以尽快得到结果。
但是,另一方面,如果你判断相等性的方法很简单,而且在实际使用中不太可能把一个对象和它自己进行比较,那么这个先检查是否相同的步骤就可能是多余的。
举个例子,如果判断两个对象是否相等只需要比较一两个整数,那么这个方法会比检查它们是否是同一个对象更快。这样,你在比较它们的 id
之前,就能得到答案。而且要记住,如果你先检查了它们的身份,发现它们的 id
不一样(在大多数情况下是这样的),那么你就没有得到任何好处,因为你还得进行完整的相等性检查。
所以,如果完整的相等性检查比较耗时,并且有可能一个对象会和它自己进行比较,那么先检查身份是个不错的主意。
另外一个原因是,默认情况下不进行身份检查是因为,有些情况下,两个身份相同的对象可能会被认为是不相等的,这种情况虽然少见,但也是合理的。例如:
>>> s = float('nan')
>>> s == s
False
必要性:不需要
这样做有意义吗:当然,有什么不好呢?
默认情况下并没有进行这样的检查,正如你在这里看到的:
class bad(object):
def __eq__(self, other):
return False
x = bad()
print x is x, x==x # True, False