Как я понял, декодер total_ordering
от functools
не должен хорошо работать с классами, унаследованными от упорядоченного класса: он не пытается определить функции сравнения, поскольку они уже определены.Total_ordering и наследование классов
Смотрите этот пример:
from functools import total_ordering
from collections import namedtuple
Test = namedtuple('Test',['a','b'])
@total_ordering
class TestOrd(Test):
def __lt__(self,other):
return self.b < other.b or self.b == other.b and self.a < other.a
x = TestOrd(a=1,b=2)
y = TestOrd(a=2,b=1)
print(x < y) # Expected: False
print(x <= y) # False
print(x > y) # True
print(x >= y) # True
print(y < x) # True
print(y <= x) # True
print(y > x) # False
print(y >= x) # False
Из всех тестов, только те, с участием оператора <
дают ожидаемый результат.
Я также могу использовать >
, добавив __gt__ = lambda *_ : NotImplemented
к определению класса. С другой стороны, если добавить аналогичные определения для __le__
или __ge__
, соответствующие тесты не с (для __le__
):
TypeError: unorderable types: TestOrd() <= TestOrd()
, что приводит меня к мысли, что это не правильный способ решения этой проблемы.
Таким образом, вопрос: есть правильный способ изменить порядок класса с total_ordering?
(Да, я знаю, что делает работу total_ordering
«s вручную тривиально, и я знаю, что для этого примера, определяя неупорядоченный namedtuple
тривиален тоже.)
* «Есть ли способ переупорядочить класс с total_ordering?«* - нет, как вы указываете, это заменит только те методы, которые еще не определены, поэтому класс наследования должен переопределить все из них явно, чтобы изменить порядок. – jonrsharpe
@jonrsharpe Может быть, способ отметить какой-то метод как неопределенный? , это можно сделать для '>' например ... –
Я не думаю, что вы понимаете, что это делает, это не влияет на 'total_ordering' (который ищет * существование *, а не * реализацию *). вы удаляете декоратор, поведение не изменится. Я полагаю, вы могли бы создать новый декоратор оформления, который будет выглядеть только в методах, определенных непосредственно на этом конкретном классе (проверьте в '__dict__', а не' dir'). – jonrsharpe