Создание класса, определяемого пользователем python, сортируемого, хешируемого
Какие методы нужно переопределять/реализовывать при создании пользовательских классов, сортируемых и/или хешируемых в python?
Зачем нужны часовые?
Я набираю dir({})
в свой интерпретатор, чтобы получить список методов на встроенных dicts. Из них я предполагаю, что мне нужно некоторое реализовать некоторое подмножество
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
Есть ли разница в том, какие методы должны быть реализованы для Python3, а не Python2?
Ответы
Ответ 1
Я почти разместил это как комментарий к другим ответам, но это действительно ответ сам по себе.
Чтобы сортировать элементы, им нужно реализовать __lt__
. Это единственный метод, используемый встроенной сортировкой.
Другие сравнения или functools.total_ordering
необходимы, только если вы действительно хотите использовать операторы сравнения с вашим классом.
Чтобы сделать ваши элементы хешируемыми, вы реализуете __hash__
, как отмечали другие. Вы также должны реализовать __eq__
совместимым способом - элементы, эквивалентные, должны иметь то же самое.
Ответ 2
Там нет никакой разницы между Python 2 и 3.
Для сортировки:
Вы должны определить методы сравнения. Это делает ваши предметы сортируемыми. Как правило, вы не должны предпочитать __cmp__()
.
Я обычно использую functools.total_ordering decorator.
functools.total_ordering (cls) Учитывая класс, определяющий один или несколько методов упорядочения с богатым сравнением, этот декоратор класса предоставляет остальное. Это упрощает усилия по определению всех возможных операций расширенного сравнения:
Класс должен определять один из __lt__()
, __le__()
, __gt__()
или __ge__()
. Кроме того, класс должен предоставлять __eq__()
.
Вы должны быть осторожны, чтобы ваши методы сравнения не имели побочных эффектов. (изменить любое из значений объекта)
Для перемешивания:
Вы должны реализовать __hash__()
. Я думаю, что лучший способ вернуть hash(repr(self))
, поэтому ваш хеш будет уникальным.
Ответ 3
Существует несколько способов сортировки вашего объекта. Первое - богатое сравнение, определяемое набором функций:
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
Также можно определить только одну функцию:
object.__cmp__(self, other)
И последнее должно быть определено, если вы хотите определить пользовательскую функцию __hash__
. См. doc.
Ответ 4
Реализовать метод __lt__(self,other)
- это ответ, чтобы сделать ваш класс сортируемым.
Он может использоваться не только для встроенного метода sorted(iterable)
, но и для очереди приоритетов через модуль heapq
.
Кроме того, мне не нравится дизайн python, поэтому многие методы '__ge__', '__gt__', '__le__', '__lt__', '__ne__'
не интуитивно понятны!
В отличие от Java Interface Comparable<T>
(см. java doc) возвращает отрицательное целое число, ноль или положительное целое число, так как этот объект меньше, равный или больший, чем указанный объект, который прямой и дружественный!