使Python用户定义类可排序、可哈希

132 投票
4 回答
87563 浏览
提问于 2025-04-17 00:08

在Python中,当你想让自己定义的类可以排序或者可以被哈希时,需要重写或实现哪些方法呢?

在这个过程中,有哪些需要注意的地方呢?

我在我的解释器里输入了 dir({}),这样可以得到内置字典(dict)的方法列表。在这些方法中,我想我需要实现其中的一部分。

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

在Python3和Python2中,必须实现的方法有什么不同吗?

4 个回答

7

有几种方法可以让你的对象可以排序。首先是丰富比较,这需要通过一组函数来定义:

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__ 函数,也需要定义这个。具体可以查看文档

35

Python 2和Python 3之间没有什么区别。

关于可排序性:

你需要定义比较方法,这样你的对象才能被排序。一般来说,不建议使用 __cmp__() 方法。

我通常会使用 functools.total_ordering 装饰器。

functools.total_ordering(cls) 是一个类装饰器,它可以为定义了一个或多个丰富比较方法的类提供其他比较方法。这可以简化你在指定所有可能的丰富比较操作时的工作量:

这个类必须定义以下之一:__lt__()__le__()__gt__()__ge__()。此外,类还应该提供一个 __eq__() 方法。

你需要注意,比较方法不要有任何副作用,也就是说,不要改变对象的任何值。

关于哈希:

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

149

我差点把这个当作评论发到其他回答下面,但其实它本身就是一个答案。

要让你的项目可以排序,只需要实现一个叫做 __lt__ 的方法。这是内置排序时唯一会用到的方法。

其他的比较方法或者 functools.total_ordering 只有在你想用比较运算符来操作你的类时才需要。

要让你的项目可以被哈希(也就是可以用作字典的键),你需要实现 __hash__,正如其他人提到的那样。你还应该以兼容的方式实现 __eq__ —— 也就是说,相等的项目应该有相同的哈希值。

撰写回答