Elad Weiss
Elad Weiss

Reputation: 4002

python - native approach to comparing objects

I have a simple python class, that I want to be able to compare. So I implemented compare operators. I then realized that I've been doing that same thing for so many classes, and it feels a lot like code duplication.

class Foo(object):
    def __init__(self, index, data):
        self.index = index
        self.data = data

    def __lt__(self, other):
        return self.index < other.index

    def __gt__(self, other):
        return self.index > other.index

    def __le__(self, other):
        return self.index <= other.index

    def __ge__(self, other):
        return self.index >= other.index

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

    def __ne__(self, other):
        return self.index != other.index

So I think a simple solution would be something like this:

class Comparable(object):
    def _compare(self, other):
        raise UnimplementedError()

    def __lt__(self, other):
        return self._compare(other) < 0

    def __gt__(self, other):
        return self._compare(other) > 0

    def __le__(self, other):
        return self._compare(other) <= 0

    def __ge__(self, other):
        return self._compare(other) >= 0

    def __eq__(self, other):
        return self._compare(other) == 0

    def __ne__(self, other):
        return self._compare(other) != 0

class Foo1(Comparable):
    def _compare(self, other):
        return self.index - other.index

class Foo2(Comparable):
    def _compare(self, other):
        # ...

class Foo3(Comparable):
    def _compare(self, other):
        # ...

But it seems so basic, that I feel like I'm reinventing the wheel here.

I'm wondering if there a more 'native' way to achieve that.

Upvotes: 0

Views: 104

Answers (2)

galmeriol
galmeriol

Reputation: 461

So, you want some automation while creating rich comparison methods. You can have this behaviour by using functools.total_ordering() higher-order function. See the reference for more details.

Upvotes: 1

Cory Kramer
Cory Kramer

Reputation: 117866

As described in the docs you can use functools.total_ordering to save some boilerplate in writing all of the comparisons

To avoid the hassle of providing all six functions, you can implement __eq__, __ne__, and only one of the ordering operators, and use the functools.total_ordering() decorator to fill in the rest.

To be explicit, the six functions they are referring to are: __eq__, __ne__, __lt__, __le__, __gt__, and __ge__.

Upvotes: 2

Related Questions