使Python用户定义类可排序、可哈希
在Python中,当你想让自己定义的类可以排序或者可以被哈希时,需要重写或实现哪些方法呢?
在这个过程中,有哪些需要注意的地方呢?
我在我的解释器里输入了 dir({})
,这样可以得到内置字典(dict)的方法列表。在这些方法中,我想我需要实现其中的一部分。
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
在Python3和Python2中,必须实现的方法有什么不同吗?
4 个回答
有几种方法可以让你的对象可以排序。首先是丰富比较,这需要通过一组函数来定义:
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__
函数,也需要定义这个。具体可以查看文档。
Python 2和Python 3之间没有什么区别。
关于可排序性:
你需要定义比较方法,这样你的对象才能被排序。一般来说,不建议使用 __cmp__()
方法。
我通常会使用 functools.total_ordering
装饰器。
functools.total_ordering(cls)
是一个类装饰器,它可以为定义了一个或多个丰富比较方法的类提供其他比较方法。这可以简化你在指定所有可能的丰富比较操作时的工作量:这个类必须定义以下之一:
__lt__()
、__le__()
、__gt__()
或__ge__()
。此外,类还应该提供一个__eq__()
方法。
你需要注意,比较方法不要有任何副作用,也就是说,不要改变对象的任何值。
关于哈希:
你应该实现 __hash__()
方法。我认为最好的方法是返回 hash(repr(self))
,这样你的哈希值就会是唯一的。
我差点把这个当作评论发到其他回答下面,但其实它本身就是一个答案。
要让你的项目可以排序,只需要实现一个叫做 __lt__
的方法。这是内置排序时唯一会用到的方法。
其他的比较方法或者 functools.total_ordering
只有在你想用比较运算符来操作你的类时才需要。
要让你的项目可以被哈希(也就是可以用作字典的键),你需要实现 __hash__
,正如其他人提到的那样。你还应该以兼容的方式实现 __eq__
—— 也就是说,相等的项目应该有相同的哈希值。