Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a python user-defined class sortable, hashable

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?

like image 500
Matt Fenwick Avatar asked Aug 22 '11 19:08

Matt Fenwick


People also ask

How do I make a custom class hashable in Python?

If you want to make your classes hashable, you must follow two rules outlined in the Python Glossary for the entry for "hashable": An object is hashable if [1] it has a hash value which never changes during its lifetime (it needs a __hash__() method), and can be compared to other objects (it needs an __eq__() method).

Are User-Defined Objects hashable in Python?

From the Python3 docs circa 5 March 2021: Objects which are instances of user-defined classes are hashable by default. They all compare unequal (except with themselves), and their hash value is derived from their id().

Is a Python class hashable?

All immutable built-in objects in Python are hashable like tuples while the mutable containers like lists and dictionaries are not hashable. Objects which are instances of the user-defined class are hashable by default, they all compare unequal, and their hash value is their id().

How do you make an object hashable?

An object hash is an integer number representing the value of the object and can be obtained using the hash() function if the object is hashable. To make a class hashable, it has to implement both the __hash__(self) method and the aforementioned __eq__(self, other) method. As with equality, the inherited object.


2 Answers

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.

like image 125
agf Avatar answered Oct 09 '22 09:10

agf


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.

like image 42
utdemir Avatar answered Oct 09 '22 08:10

utdemir