У меня есть вопрос относительно поведения python '> ='.python> = оператор на классах
У меня есть старый класс TimeStamp, который содержит (час, минута) кортеж и предлагает некоторые методы, такие как __eq__
, __gt__
, __lt__
.
Я рефакторинг, чтобы он также учитывал день и секунду, и хранить данные в виде полных секунд. Здесь я внедрил __eq__
, __gt__
, __lt__
.
Однако далее в коде я использую> = оператор для этого класса и в то время как старая версия класса работает должным образом, с новым я получаю
TypeError: unorderable types: TimeStamp() >= TimeStamp() error.
код ниже:
class TimeStamp(tuple): # OLD, WORKING VERSION
"""TimeStamp, hh:mm tuple supporting comparison and addition"""
__slots__ =()
def __new__(cls, *args):
if len(args) == 1: # tuple entrance
hour, minute = args[0]
elif len(args) == 2: # hour, minute entrance
hour, minute = args[0], args[1]
else:
raise TypeError('wrong input to TimeStamp')
div, minute = divmod(minute, 60)
hour += div
_, hour = divmod(hour, 24)
return tuple.__new__(cls, (hour, minute))
@property
def abs_min(self):
return self.hour * 60 + self.minute
def __gt__(self, rhs):
return self.abs_min > rhs.abs_min
def __lt__(self, rhs):
return self.abs_min < rhs.abs_min
def __eq__(self, rhs):
return self.abs_min == rhs.abs_min
Новая версия:
class TimeStamp:
def __init__(self, *args):
for argument in args:
if not isinstance(argument, int):
raise TypeError("Can only build TimeStamp from ints, not: " + str(argument))
if len(args) == 1: # init by abs
self.abs = args[0] # put the ELEMENT, not the tuple itself
elif len(args) == 2: # init by hour:minute
hour, minute = args
self.abs = hour * 60 * 60 + minute * 60
elif len(args) == 4: #init by day:hour:minute:second
day, hour, minute, second = args
self.abs = day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second
else:
raise TypeError("wrong data for TimeStamp: " + str(args))
def __eq__(self, other):
if isinstance(other, TimeStamp):
return self.abs == other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
def __gt__(self, other):
if isinstance(other, TimeStamp):
return self.abs > other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
def __lt__(self, other):
if isinstance(other, TimeStamp):
return self.abs < other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
Теперь для части сравнения:
if args[1] >= self.start:
>>TypeError: unorderable types: TimeStamp() >= TimeStamp()
Я нашел два исправления: первое, чтобы заменить мою сравнительную линию с
if args[1] > self.start or args[1] == self.start:
или альтернативы, чтобы добавить
def __ge__(self, other):
if isinstance(other, TimeStamp):
return self.abs >= other.abs
else:
raise TypeError("wrong argument for comparison: " + str(other))
к моему новому классу. Однако старый не работал ни с одним из этих исправлений. Мне кажется, что Python прекратил вычитать, что ((a> b) или (a == b)) подразумевает (a> = b). Но зачем это работало раньше? Имеет ли это что-то общее со мной, подклассифицируя кортеж?
PS. не бойтесь моего кода __init__
, который я включил для полноты. Это должно быть от перегрузки, как, но я мог бы делать это в не вещий образом (по-прежнему обучения)
Что произойдет, если вы наследуете TimeStamp от 'object'? – mgilson
Вы также можете проверить 'functools.total_ordering', чтобы вы не могли самостоятельно писать все богатые методы сравнения. – mgilson
Заключительный комментарий. Вместо того, чтобы поднимать 'TypeError', вы должны возвращать' NotImplemented'. Нет причин говорить другим классам, что они не могут сравниться с 'TimeStamp', если они знают, как это сделать.(Он также устраняет фанковые ошибки, такие как 'time_stamp> my_class', поднимающий TypeError, но' my_class <= time_stamp' работает просто отлично) – mgilson