Making a python user-defined class sortable, hashable

PythonClassSortingHashMagic Methods

Python Problem Overview


What methods need to be overridden/implemented when making user-defined classes sortable and/or hashable in python?

What are the gotchas to watch out for?

I type dir({}) into my interpreter to get a list of methods on built-in dicts. Of those, I assume I need to some implement some subset of

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

Is there a difference in which methods must be implemented for Python3 as opposed to Python2?

Python Solutions


Solution 1 - Python

I almost posted this as a comment to the other answers but it's really an answer in and of itself.

To make your items sortable, they only need to implement __lt__. That's the only method used by the built in sort.

The other comparisons or functools.total_ordering are only needed if you actually want to use the comparison operators with your class.

To make your items hashable, you implement __hash__ as others noted. You should also implement __eq__ in a compatible way -- items that are equivalent should hash the same.

Solution 2 - Python

There isn't any difference between Python 2 and 3.

For sortability:

You should define comparision methods. This makes your items sortable. Generally, you shouldn't prefer __cmp__().

I usually use functools.total_ordering decorator.

> functools.total_ordering(cls) Given a class defining one or more rich > comparison ordering methods, this class decorator supplies the rest. > This simplifies the effort involved in specifying all of the possible > rich comparison operations: > > The class must define one of __lt__(), __le__(), __gt__(), or > __ge__(). In addition, the class should supply an __eq__() method.

You should be careful that your comparison methods do not have any side effects. (change any of the values of the object)

For hashing:

You should implement __hash__() method. I think the best way is returning hash(repr(self)), so your hash would be unique.

Solution 3 - Python

There are a few ways of marking your object sortable. First - rich comparison, defined by a set of functions:

object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)

Also it is possible to define only one function:

object.__cmp__(self, other)

And the last should be defined if you want to define custom __hash__ function. See the doc.

Solution 4 - Python

Implement __lt__(self,other) method is the answer to make your class sortable.
It can be used for not only the built-in method sorted(iterable), but also priority queue via heapq module.

In addition, I don't like python's design, so many '__ge__', '__gt__', '__le__', '__lt__', '__ne__' methods are not intuitive at all !
As a contrast, Java's Interface Comparable<T> (see java doc) returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object, which is direct and friendly!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatt FenwickView Question on Stackoverflow
Solution 1 - PythonagfView Answer on Stackoverflow
Solution 2 - PythonutdemirView Answer on Stackoverflow
Solution 3 - PythonRoman BodnarchukView Answer on Stackoverflow
Solution 4 - PythonyichuduView Answer on Stackoverflow