6
class x:
    def __init__(self,name):
        self.name=name

    def __str__(self):
        return self.name

    def __cmp__(self,other):
        print("cmp method called with self="+str(self)+",other="+str(other))
        return self.name==other.name
       # return False


instance1=x("hello")
instance2=x("there")

print(instance1==instance2)
print(instance1.name==instance2.name)

The output here is:

cmp method called with self=hello,other=there
True
False

Which is not what I expected: I'm trying to say 'two instances are equal if the name fields are equal'.

If I simply return False from the __cmp__ function, this reports as True as well!! If I return -1, then I get False - but since I'm trying to compare strings, this doesn't feel right.

What am I doing wrong here?

SilentGhost
  • 307,395
  • 66
  • 306
  • 293
monojohnny
  • 5,894
  • 16
  • 59
  • 83

5 Answers5

10

__cmp__(x,y) should return a negative number (e.g. -1) if x < y, a positive number (e.g. 1) if x > y and 0 if x == y. You should never return a boolean with it.

What you're overloading is __eq__(x, y).

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Thankyou - you get the tickmark (even though other people provided similar information), as this is the clearest explanation! – monojohnny Jan 27 '10 at 12:41
  • As others commented, __cmp__() is obsolete. Define __lt__(), __eq__(), and __gt__() instead. As per http://docs.python.org/dev/whatsnew/3.0.html#ordering-comparisons – smci Jun 30 '11 at 03:51
5

the __cmp__ method should return -1, 0 or 1, when self < other, self == other, self > other respectvelly.

You can do

return cmp(self.name, other.name)

in your code for a proper result

Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
jsbueno
  • 99,910
  • 10
  • 151
  • 209
4

You're confusing __cmp__ with __eq__.

From the documentation of __cmp__:

Should return a negative integer if self < other, zero if self == other, a positive integer if self > other.

__eq__ returns a boolean which determines if two objects are equal, __cmp__ returns an integer which determines if the two objects are greater or less than each other, and so is called unless you have specific __eq__, __ne__, __le__, __ge__, __lt__ and __gt__ methods.

In your case you do want a __cmp__ method rather than __eq__ as it will save you implementing the other 5 methods for the other comparisons.

You could use the cmp() function and put the following in your __cmp__ method:

return cmp(self.name,other.name)

Note, as highlighted by Ignacio is this isn't the preferred method in Python 3.0, but in Python 2.x __cmp__ is the way to go.

Community
  • 1
  • 1
David Webb
  • 190,537
  • 57
  • 313
  • 299
2

__cmp__() is obsolescent. Define __lt__(), __eq__(), and __gt__() instead.

Even so, you're doing it wrong. You're supposed to return an integer.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • "obsolescent"?? Where did you pick this from? The others exist, but in most cases it makes more sense to use __cmp__, in this case, for example, it would take 3 methods instead of just one. http://docs.python.org/reference/datamodel.html – jsbueno Jan 27 '10 at 11:07
  • 1
    @jsbueno: Third bullet point: http://docs.python.org/dev/3.0/whatsnew/3.0.html#ordering-comparisons – Ignacio Vazquez-Abrams Jan 27 '10 at 11:11
  • URL has moved to http://docs.python.org/dev/whatsnew/3.0.html#ordering-comparisons – smci Jun 30 '11 at 03:49
0

Lookup the documentation for __cmp__, youre supposed to return an integer:

Should return a negative integer if self < other, zero if self == other, a positive integer if self > other.

Mizipzor
  • 51,151
  • 22
  • 97
  • 138