使 Python 用户定义的类可排序、散列

在 python 中使用户定义的类可排序和/或散列时,需要覆盖/实现哪些方法?

What are the gotchas to watch out for?

我在解释器中键入 dir({}),以获得内置 dicts 上的方法列表。其中,我假设我需要实现

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

必须为 Python 3实现哪些方法与为 Python 2实现哪些方法有区别吗?

69240 次浏览

有几种方法可以标记对象的可排序性。第一种是富比较,由一组函数定义:

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__函数,则应该定义最后一个函数。

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

对于可分类性:

您应该定义比较方法。这使您的项目可排序。一般来说,您不应该更喜欢 __cmp__()

I usually use functools.total_ordering decorator.

Total _ order (cls)给定一个定义一个或多个 rich 的类 比较排序方法,这个类装饰符提供其余的。 This simplifies the effort involved in specifying all of the possible 丰富的比较操作:

该类必须定义 __lt__()__le__()__gt__()__ge__(). In addition, the class should supply an __eq__() method.

您应该小心,您的比较方法不会有任何副作用。(更改对象的任何值)

散列:

你应该实现 __hash__()方法。我认为最好的方法是返回 hash(repr(self)),这样你的散列就是唯一的。

我几乎把这个作为对其他答案的评论贴出来了,但它本身就是一个真正的答案。

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

只有在您确实希望在类中使用比较运算符时,才需要其他比较或 functools.total_ordering

为了使您的项目散列化,您实现了 __hash__,正如其他人指出的那样。您还应该以兼容的方式实现 __eq__——等效的项应该使用相同的散列。

实现 __lt__(self,other)方法是使类可排序的答案。
它不仅可以用于 sorted(iterable)内置方法,而且可以通过 heapq模块实现优先级队列。

另外,我不喜欢 python 的设计,所以很多 '__ge__', '__gt__', '__le__', '__lt__', '__ne__'方法都是 not intuitive at all
作为对比,Java 的 Interface Comparable<T>(参见 爪哇医生)返回一个负整数、零或正整数,因为这个对象小于、等于或大于指定的对象,即 直接友好