Carsten
Carsten

Reputation: 2040

Define class attribute for all comparisons

I have a Python class like this:

@dataclass
class Person:
    name: str
    relatives: Iterable['Person']

I want to use the name attribute for all comparisons, so that Person objects are sorted alphabetically by default. Hence, I override the __gt__() method like this (as described in the documentation):

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

This actually resolves my initial task, I can do e.g.:

p1=Person("test1", relatives=[])
p2=Person("test2", relatives=[])
sorted([p1, p2])
Out[4]: [Person(name='test1', relatives=[]), Person(name='test2', relatives=[])]

As well as this:

p1>p2
Out[5]: False
p1<p2
Out[6]: True

I understand that I don't have to implement all operators:

__lt__() and __gt__() are each other’s reflection, __le__() and __ge__() are each other’s reflection, and __eq__() and __ne__() are their own reflection.

For equality comparison, however, I still have to override __eq__(other) explicitly:

    def __eq__(self, other):
        return isinstance(other, Person) and self.name == other.name

Is there a way to implement this in a more concise way? I would envision some way to tell the interpreter 'use attribute name for all comparisons!'.

Upvotes: 1

Views: 218

Answers (1)

Daweo
Daweo

Reputation: 36680

If providing __eq__ and at least 1 of rich comparison is okay in your case you might use functools.total_ordering decorator, like so:

import functools
@functools.total_ordering
class Name:
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.name
    def __eq__(self, other):
        return self.name == other.name
    def __gt__(self, other):
        return self.name > other.name
a = Name("a")
b = Name("b")
print(a<b)
print(a<=b)
print(b>=a)

output

True
True
True

If this is not accepable in your case you would need to prepare own decorator to use, for discussion of decorating class see How to decorate a class

Upvotes: 4

Related Questions