Python - нативный подход к сравнению объектов

У меня есть простой класс Python, который я хочу сравнить. Итак, я реализовал операторы сравнения. Затем я понял, что делаю то же самое для очень многих классов, и это очень похоже на дублирование кода.

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

Поэтому я думаю, что простое решение будет примерно таким:

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):
        # ...

Но это кажется настолько простым, что я чувствую, что изобретаю велосипед здесь.

Мне интересно, есть ли более «естественный» способ добиться этого.

Для чего-то такого базового вы можете просто реализовать __cmp__ вместо каждой отдельной операции.

MrAlexBailey 11.04.2018 13:20

@Jkdc Это именно то, что я искал! Жалко для поддержки Python 3 :(

Elad Weiss 11.04.2018 13:24

Вы можете использовать PY3__cmp__ класс миксина

Mike Scotty 11.04.2018 13:26
0
4
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Как описано в документах, вы можете использовать functools.total_ordering, чтобы сохранить некоторый шаблон при написании всех сравнений.

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.

Чтобы быть точным, они имеют в виду шесть функций: __eq__, __ne__, __lt__, __le__, __gt__ и __ge__.

Итак, вам нужна автоматизация при создании методов богатое сравнение. Вы можете получить такое поведение, используя функцию высшего порядка functools.total_ordering(). Подробнее см. Справка.

Другие вопросы по теме