tags:

views:

1873

answers:

6

What is the best way to compare two instances of some object for equality in Python? I'd like to be able to do something like

Example:

doc1 = ErrorDocument(path='/folder',title='Page')
doc2 = ErrorDocument(path='/folder',title='Page')

if doc1 == doc2: # this should be True
    #do something

EDIT:

To further clarify the question. I'd like to compare by attribute values, and to make a more generic solution than

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

Should the __eq__() method look something like this?

def __eq__(self, other):
    # Is the other instance of the same object
    # Loop through __dict__ and compare values to attributes of other
+1  A: 

When comparing instances of objects, the cmp function is called.

If the == operator is not working for you by default, you can always redefine the cmp function for the object.

Edit:

As has been pointed out, the cmp function is deprecated since 3.0. Instead you should use the “rich comparison” methods.

Silfverstrom
The __cmp__ function is deprecated for 3.0+
Christopher
Yes, see http://stackoverflow.com/questions/1061283/style-why-lt-instead-of-cmp
Kiv
Ah!You learn something new everyday;d
Silfverstrom
+2  A: 

Implement the __eq__ method in your class; something like this:

def __eq__(self, other):
    return self.path == other.path and self.title == other.title

Edit: if you want your objects to compare equal if and only if they have equal instance dictionaries:

def __eq__(self, other):
    return self.__dict__ == other.__dict__
Kiv
Perhaps you mean `self is other` to see if they are the same object.
S.Lott
-1. Even if this is two dictionary instance, Python will compare them by keys / values automatically. This is not Java...
e-satis
+2  A: 

You override the rich comparison operators in your object.

class MyClass:
 def __lt__(self, other):
      # return comparison
 def __le__(self, other)
      # return comparison
 def __eq__(self, other)
      # return comparison
 def __ne__(self, other)
      # return comparison
 def __gt__(self, other)
      # return comparison
 def __ge__(self, other)
      # return comparison
Christopher
A: 

Instance of a class when compared with == comes to non-equal. The best way is to ass the cmp function to u r class which will do the stuff.

If u want to do comparison by the content u can simply use cmp(obj1,obj2)

In u r case cmp(doc1,doc2) It will return -1 if the content wise thy are same.

asb
-1, did you even read the other answers?
Kiv
+6  A: 

As usual with Python, it's kiss :

class Test(object) :

    def __init__(self, attr1, attr2) :
        self.attr1 = attr1
        self.attr2 = attr2

    def __str__(self) :
        return str(self.__dict__)

    def __eq__(self, other) : 
        return self.__dict__ == other.__dict__

t1 = Test("foo", 42)
t2 = Test("foo", 42)
t3 = Test("bar", 42)

print t1, t2, t3
print t1 == t2
print t2 == t3

It outputs :

{'attr2': 42, 'attr1': 'foo'} {'attr2': 42, 'attr1': 'foo'} {'attr2': 42, 'attr1': 'bar'}
True
False

N.B : be aware that before Python 3.0, you are more likely to use __cmp__ instead of __eq__, working the same way.

e-satis
Good answer, but spaces before colons? That's a PEP 8 no-no ;)
Kiv
LOL, yeah i'm french, we write with spaces before colons, and before ? and ! too. Sometimes I even write comment in French, shame on me :-)
e-satis
Note that with this technique, a Test instance will also compare equal to any other instance who's dictionary compares equal. You may also want "isinstance(other, self.__class__)" in __eq__.
Jason R. Coombs
That would kill the nice duck typing we got here. It's not like there is a big likely hood that two classes have the exact same signature and that your willingly compare it to each other. And without knowing it.
e-satis
+1  A: 

You can speed things little by using a Hash

class ErrorDocument(object):
    def __init__(self, path, name):
        self.path = path
        self.name = name
        self.uid = hash(path + name)

    def __eq__(self, other):
        return self.uid == other.uid

This of course will only work to compare ErrorDocument objects.

Ubersoldat