在python中对用户定义的类进行排序和/或哈希时,需要覆盖/实现哪些方法?
有什么值得注意的?
我在我的解释器中输入dir({})
以获取内置dicts的方法列表。其中,我假设我需要实现一些
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
与Python2相比,Python3必须实现哪些方法有区别?
答案 0 :(得分:68)
我几乎将此作为对其他答案的评论发布,但它本身就是一个答案。
要使您的商品可排序,他们只需要实施__lt__
。这是内置排序使用的唯一方法。
只有在您真正想要将比较运算符与您的班级一起使用时,才需要进行其他比较或functools.total_ordering
。
要使您的商品可以播放,请按照其他人的说明实施__hash__
。您还应该以兼容的方式实现__eq__
- 相同的项应该使用相同的哈希值。
答案 1 :(得分:15)
Python 2和3之间没有任何区别。
可分类性:
您应该定义比较方法。这使您的商品可以排序。通常,您不应该更喜欢__cmp__()
。
我通常使用functools.total_ordering装饰器。
functools.total_ordering(cls)给定一个定义一个或多个rich的类 比较排序方法,这个类装饰器提供其余的。 这简化了指定所有可能的工作 丰富的比较操作:
该课程必须定义
__lt__()
,__le__()
,__gt__()
或其中一个__ge__()
。此外,该课程应提供__eq__()
方法。
您应该注意比较方法是否有副作用。在进行比较时,您不希望更改班级。
用于散列:
您应该实施__hash__()
方法。我认为最好的方法是返回hash(repr(self))
,所以你的哈希值是唯一的。
答案 2 :(得分:2)
有几种方法可以将对象标记为可排序。第一个 - 丰富的比较,由一组函数定义:
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__
函数,则应定义最后一个。请参阅doc。
答案 3 :(得分:-1)
实施__lt__(self,other)
方法是让您的课程可排序的答案
它不仅可以用于内置方法sorted(iterable)
,还可以用于heapq
模块的优先级队列。
另外,我不喜欢python的设计,因此很多'__ge__', '__gt__', '__le__', '__lt__', '__ne__'
方法根本不直观!
相比之下,Java的Interface Comparable<T>
(请参阅java doc)返回负整数,零或正整数,因为此对象小于,等于或大于指定对象,即直接友好!