Какие методы необходимо переопределить / реализовать при создании сортируемых и / или хешируемых пользовательских классов в Python?
Какие подводные камни следует остерегаться?
Я ввожу dir({})
свой интерпретатор, чтобы получить список методов для встроенных dicts. Из них, я полагаю, мне нужно реализовать какое-то подмножество
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
Есть ли разница в том, какие методы должны быть реализованы для Python3, а не для Python2?
__cmp__
была удалена.Ответы:
Я почти опубликовал это как комментарий к другим ответам, но это действительно ответ сам по себе.
Чтобы ваши предметы можно было сортировать, их нужно всего лишь реализовать
__lt__
. Это единственный метод, используемый встроенной сортировкой.Другие сравнения
functools.total_ordering
необходимы только в том случае, если вы действительно хотите использовать операторы сравнения с вашим классом.Чтобы сделать ваши элементы хешируемыми, вы реализуете,
__hash__
как отметили другие. Вы также должны реализовать__eq__
совместимым способом - элементы, которые эквивалентны, должны иметь одинаковый хэш.источник
__lt__
может привести к непредсказуемой сортировке Python? (например, if x .__ lt __ (y) и y .__ lt __ (x))__key__
функцию, которая превращает экземпляр в кортеж, а затем просто используйте его как__lt__
(self.__key__() < other.__key__()
), так и__hash__
(hash(self.__key__())
).Между Python 2 и 3 нет никакой разницы.
Для сортировки:
Вы должны определить методы сравнения. Это позволяет сортировать ваши предметы. Как правило, вы не должны отдавать предпочтение
__cmp__()
.Обычно я использую декоратор functools.total_ordering.
Вы должны быть осторожны, чтобы ваши методы сравнения не имели побочных эффектов. (изменить любое из значений объекта)
Для хеширования:
Вы должны реализовать
__hash__()
метод. Думаю, лучший способ - вернутьсяhash(repr(self))
, чтобы ваш хеш был уникальным.источник
functools.total_ordering
из документации см. Здесь .Есть несколько способов пометить объект как объект сортировки. Первый - богатое сравнение, определяемое набором функций:
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__
функцию. См. Док .источник
__cmp__()
специальный метод больше не поддерживается», см. Соответствующий раздел здесь .__lt__(self,other)
Метод реализации - это ответ, позволяющий упорядочить ваш класс.Его можно использовать не только для встроенного метода
sorted(iterable)
, но и для очереди приоритетов черезheapq
модуль.Кроме того, мне не нравится дизайн Python, поэтому многие
'__ge__', '__gt__', '__le__', '__lt__', '__ne__'
методы вообще не интуитивно понятны !Напротив, Java
Interface Comparable<T>
(см. Java doc ) возвращает отрицательное целое число, ноль или положительное целое число, поскольку этот объект меньше, равен или больше указанного объекта, что является прямым и понятным !источник