在python中使用户定义的类可排序和/或可哈希化时,需要重写/实现哪些方法?
需要注意的陷阱是什么?
我输入dir({})
解释器以获取内置字典的方法列表。其中,我假设我需要一些实现
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
与Python2相比,必须为Python3实现哪些方法有区别吗?
Answers:
我差点把它作为对其他答案的评论,但这本身就是一个答案。
为了使您的项目可排序,它们只需要实现__lt__
。这是内置排序使用的唯一方法。
其他比较还是functools.total_ordering
仅在您确实要对类使用比较运算符时才需要。
为了使您的项目可散列,请__hash__
按照其他说明实施。您还应该__eq__
以兼容的方式实现-等效的项目应使用相同的哈希值。
__lt__
可能导致python发生不可预测的排序?(例如,如果x .__ lt __(y)和y .__ lt __(x))
__key__
将实例转换为元组的函数,然后同时使用__lt__
(self.__key__() < other.__key__()
)和__hash__
(hash(self.__key__())
)。
Python 2和3之间没有任何区别。
为了可分类性:
您应该定义比较方法。这使您的项目可排序。通常,您不应该首选__cmp__()
。
我通常使用functools.total_ordering装饰器。
functools.total_ordering(cls)给定一个定义了一个或多个丰富比较排序方法的类,该类装饰器提供其余的方法。这简化了指定所有可能的丰富比较操作的工作:
这个类必须定义之一
__lt__()
,__le__()
,__gt__()
,或__ge__()
。另外,该类应提供一个__eq__()
方法。
您应该小心,比较方法不会有任何副作用。(更改对象的任何值)
对于散列:
您应该实现__hash__()
方法。我认为最好的方法是返回hash(repr(self))
,因此您的哈希将是唯一的。
functools.total_ordering
文档的示例,请参见此处。
有几种标记对象可排序的方法。首先-丰富的比较,由一组函数定义:
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__
函数,则应定义最后一个。参见文档。
实施__lt__(self,other)
方法是使您的班级可排序的答案。
它不仅可以用于内置方法sorted(iterable)
,还可以用于通过heapq
模块的优先级队列。
另外,我不喜欢python的设计,所以很多'__ge__', '__gt__', '__le__', '__lt__', '__ne__'
方法根本都不直观!
相反,Java Interface Comparable<T>
(请参阅java doc)将返回负整数,零或正整数,因为此对象小于,等于或大于指定的对象,这是直接且友好的!
__cmp__
已删除。