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?
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).
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().
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().
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With