heapq push TypeError: '<' не поддерживается между экземплярами
Я работаю в Python и у меня есть проблемы с heapq. Когда я помещаю элемент в кучу, я получаю эту ошибку:
Ошибка типа: "<" не поддерживается между экземплярами "Точка" и "Точка"
Точка мой внутренний класс. Я помещаю кортеж, сформированный (float, Point), в соответствии с документацией, heapq должен использовать float в качестве ключа, но это не так. Чтобы быть более точным, иногда используйте float, но не всегда. В чем проблема?
2 ответа
heapq
будет использовать <=
оператор на все, что вы положите в него.
Кортежи сравниваются по позиции: первый элемент первого кортежа сравнивается с первым элементом второго кортежа; если они не равны (т. е. первый больше или меньше второго), то это результат сравнения, в противном случае рассматривается второй элемент, затем третий и т. д.
Если первый элемент каждого кортежа уникален, сравнение всегда будет происходить только по первому элементу:
>>> x = (1, object())
>>> y = (2, object())
>>> x <= y
True
(примечание: я использовал object()
создать анонимный объект, который не реализует операторы сравнения)
Проблема возникает, когда первый элемент кортежа не является уникальным (т. Е. Первый элемент кортежа будет равен для некоторой пары кортежей), тогда для сравнения придется сравнить второй элемент кортежа:
>>> z = (1, object())
>>> x <= z
Traceback (most recent call last):
File "<input>", line 1, in <module>
x <= z
TypeError: '<=' not supported between instances of 'object' and 'object'
Таким образом, либо вы реализуете операторы сравнения в своем объекте, либо убедитесь, что предыдущие элементы в кортеже всегда сопоставимы и вместе являются уникальными.
Например, вы можете добавить идентификатор объекта в кортеж, чтобы ваши кортежи стали:
(priority, id(obj), obj)
так как идентификатор объекта уникален. (будьте осторожны: вы снова столкнетесь с этой проблемой, если добавите два экземпляра одного и того же объекта с одинаковым приоритетом).
Вы должны определить относительные операции сравнения в вашем Point
учебный класс. Это означает:
__lt__(self, other)
за <
__le__(self,other)
за <=
и опционально
__gt__(self, other)
за >
__ge__(self, other)
за >=
,
Последние два являются необязательными, потому что, если не указано, отрицание le
а также lt
принимаются.
Общая структура этих методов __name__(self, other)
, где other
это объект, который будет сравниваться с self
, Также они возвращаются True
или же False
,
Вы также можете определить __eq__
вместо всех четырех выше, который работает как компаратор в Java. Этот метод должен возвращать положительное целое число, если self
больше, чем other
, 0, если они равны и отрицательное целое число, если other
больше чем self
,