Создание пользовательского класса Python сортируемый, хэш - PullRequest
60 голосов
/ 22 августа 2011

Какие методы необходимо переопределить / реализовать при создании пользовательских классов, сортируемых и / или хэшируемых в python?

На что нужно обращать внимание?

Я набираю dir({}) в моем интерпретаторе, чтобы получить список методов для встроенных диктов. Из них я предполагаю, что мне нужно реализовать некоторое подмножество

['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']

Есть ли разница в том, какие методы должны быть реализованы для Python3, а не для Python2?

Ответы [ 4 ]

69 голосов
/ 22 августа 2011

Я чуть не опубликовал это как комментарий к другим ответам, но это действительно ответ сам по себе.

Чтобы сделать ваши предметы сортируемыми, им нужно только реализовать __lt__. Это единственный метод, используемый встроенной сортировкой.

Другие сравнения или functools.total_ordering необходимы только в том случае, если вы действительно хотите использовать операторы сравнения с вашим классом.

Для того, чтобы сделать ваши вещи хэшируемыми, вы реализуете __hash__, как отмечали другие. Вы также должны реализовать __eq__ совместимым способом - эквивалентные элементы должны хешироваться одинаково.

15 голосов
/ 22 августа 2011

Нет никакой разницы между Python 2 и 3.

Для сортировки:

Вы должны определить методы сравнения.Это делает ваши предметы сортируемыми.Как правило, вы не должны предпочитать __cmp__().

Я обычно использую декоратор functools.total_ordering.

functools.total_ordering (cls) Учитывая класс, определяющий один или несколько методов упорядочения сравнительного сравнения, этот декоратор класса предоставляет остальное.Это упрощает усилия по определению всех возможных операций расширенного сравнения:

Класс должен определять одну из __lt__(), __le__(), __gt__() или __ge__().Кроме того, класс должен предоставлять метод __eq__().

Вы должны быть осторожны, чтобы ваши методы сравнения не имели побочных эффектов.(изменить любое из значений объекта)

Для хеширования:

Вы должны реализовать метод __hash__().Я думаю, что лучший способ вернуть hash(repr(self)), поэтому ваш хэш будет уникальным.

2 голосов
/ 22 августа 2011

Есть несколько способов пометить ваш объект как сортируемый. Первый - богатое сравнение, определяемое набором функций:

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__ функцию. См. документ .

0 голосов
/ 16 октября 2017

Реализация __lt__(self,other) - это способ сделать ваш класс сортируемым.
Его можно использовать не только для встроенного метода sorted(iterable), но и для очереди приоритетов через модуль heapq.

Кроме того, мне не нравится дизайн python, поэтому многие '__ge__', '__gt__', '__le__', '__lt__', '__ne__' методы совсем не интуитивны !
В отличие от Java Interface Comparable<T> (см. java doc *)1013 *) возвращает отрицательное целое число, ноль или положительное целое число, поскольку этот объект меньше, равен или больше указанного объекта, что является прямым и дружественным !

...