I'm doing a project in Python (3.2) for which I need to compare user defined objects. I'm used to OOP in Java, where one would define a compareTo()
method in the class that specifies the natural ordering of that class, as in the example below:
public class Foo {
int a, b;
public Foo(int aa, int bb) {
a = aa;
b = bb;
}
public int compareTo(Foo that) {
// return a negative number if this < that
// return 0 if this == that
// return a positive number if this > that
if (this.a == that.a) return this.b - that.b;
else return this.a - that.a;
}
}
I'm fairly new to classes/objects in Python, so I'd like to know what is the "pythonic" way to define the natural ordering of a class?
The equals() tells the equality of two strings whereas the compareTo() method tell how strings are compared lexicographically.
The compareTo() method compares two strings lexicographically. The comparison is based on the Unicode value of each character in the strings. The method returns 0 if the string is equal to the other string.
compareTo() in java returns an integer value. It returns a positive integer if string1 is lexicographically greater than string2, negative if string2 is greater than string1, and zero if both are equal.
The compareTo method defines the natural order; the default way for ordering objects of a class.
You can implement the special methods __lt__
, __gt__
etc. to implement the default operators for custom types. See more about them in the language reference.
For example:
class Foo:
def __init__ (self, a, b):
self.a = a
self.b = b
def __lt__ (self, other):
if self.a == other.a:
return self.b < other.b
return self.a < other.b
def __gt__ (self, other):
return other.__lt__(self)
def __eq__ (self, other):
return self.a == other.b and self.b == other.b
def __ne__ (self, other):
return not self.__eq__(other)
Or as said by stranac in the comments, you can use the total_ordering
decorator to save some typing:
@functools.total_ordering
class Foo:
def __init__ (self, a, b):
self.a = a
self.b = b
def __lt__ (self, other):
if self.a == other.a:
return self.b < other.b
return self.a < other.b
def __eq__ (self, other):
return self.a == other.b and self.b == other.b
Python has a similar function: __cmp__()
.
I now see you're asking about Python 3. Their "whats new" suggests:
The cmp() function should be treated as gone, and the __cmp__() special method is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and other rich comparisons as needed. (If you really need the cmp() functionality, you could use the expression (a > b) - (a < b) as the equivalent for cmp(a, b).)
So it seems you could always do something like
def compareTo(self, that):
return ((self > that) - (self < that))
or
@classmethod
def compare(cls, a, b):
return ((a > b) - (a < b))
after implementing __gt__()
and __lt__()
.
Which you would then use like:
f1 = Foo(1,1)
f2 = Foo(2,2)
f1.compareTo(f2)
Foo.compare(f1,f2)
This would give you equivalent functionality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With