views:

117

answers:

5

When implementing a custom equality function for a class, does it make sense to check for identity first? An example:

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

This interesting is for cases when the other criteria may be more expensive (e.g. comparing some long strings).

+3  A: 

necesarry: no

does it make sense: sure, why not?

No such check is done by default, as you can see here:

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

x = bad()
print x is x, x==x # True, False
THC4k
Thank you. So It is correct that no such check is done by default.
Space_C0wb0y
You wouldn't want the check to be done by default, see my example with `float('nan')`, which doesn't equal itself (quite legitimately).
Scott Griffiths
A: 

This is only done for performance reasons.

At one programming job I worked on, in Java, this was always done, altough it does not change any functionality.

Sjoerd
Back in my early Java days (mid-90's), testing for identity at the beginning of `equals()` was a pretty standard Java idiom.
Paul McGuire
+7  A: 

It may be a perfectly reasonable shortcut to check for identity first, and in equality methods good shortcuts (for both equality and non equality) are what you should be looking for so that you can return as soon as possible.

But, on the other hand, it could also be a completely superfluous check if your test for equality is otherwise cheap and you are unlikely in practice to be comparing an object with itself.

For example, if equality between objects can be gauged by comparing one or two integers then this should be quicker than the identity test, so in less than the time it would take to compare ids you've got the whole answer. And remember that if you check the identities and the objects don't have the same id (which is likely in most scenarios) then you've not gained anything as you've still got to do the full check.

So if full equality checking is not cheap and it's possible that an object could be compared against itself, then checking identity first can be a good idea.


Note that another reason the check isn't done by default is that it is quite reasonable (though rare) for objects with equal identities to compare as non equal, for example:

>>> s = float('nan')
>>> s == s
False
Scott Griffiths
+2  A: 

When you implement custom equality in a class, you can decide for yourself whether to check for identify first. It's entirely up to you. Note that in Python, it's also perfectly valid to decide that __eq__ and __ne__ will return the same value for a given argument; so it's possible to define equality such that identity isn't a shortcut.

It's certainly a speed improvement, although how much of one depends on the complexity of the method. I generally don't bother in my custom classes, but I don't have a lot of speed-critical code (and where I do, object comparisons aren't the hotspot).

For most of my objects, the equality method looks like:

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

I could easily add a if self is o: return True check at the beginning of the method.

Also remember to override __hash__ if you override __eq__, or you'll get odd behaviors in sets and dicts.

Chris B.
adding an if self == o would call __eq__ recursively? override __hash__ is only necessary if your object is a constant object elsewhere you couldn't hash s or dict s
Xavier Combelle
You meant `if self is o`, I think.
Paul McGuire
Fixed it, thanks.
Chris B.
+1  A: 

I asked a similar question on comp.lang.python a few years ago - here is the thread. The conclusions at that time were that the up-front identity test was worth it if you did many tests for equality of objects with themselves, or if your other equality testing logic was slow.

Paul McGuire