在 python 中使用户定义的类可排序和/或可散列时需要覆盖/实现哪些方法?
有哪些注意事项?
我dir({})
在我的解释器中输入以获取内置字典的方法列表。其中,我假设我需要一些实现一些子集
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
与 Python2 相比,必须为 Python3 实现哪些方法有区别吗?
在 python 中使用户定义的类可排序和/或可散列时需要覆盖/实现哪些方法?
有哪些注意事项?
我dir({})
在我的解释器中输入以获取内置字典的方法列表。其中,我假设我需要一些实现一些子集
['__cmp__', '__eq__', '__ge__', '__gt__', '__hash__', '__le__', '__lt__', '__ne__']
与 Python2 相比,必须为 Python3 实现哪些方法有区别吗?
我几乎将其发布为对其他答案的评论,但它本身就是一个答案。
要使您的项目可排序,它们只需要实现__lt__
. 这是内置排序使用的唯一方法。
functools.total_ordering
仅当您确实想在您的类中使用比较运算符时才需要其他比较或。
为了使您的项目可散列,您可以__hash__
按照其他人的说明实施。您还应该__eq__
以兼容的方式实现 - 等效的项目应该散列相同。
Python 2 和 3 之间没有任何区别。
对于可排序性:
您应该定义比较方法。这使您的项目可排序。一般来说,你不应该更喜欢__cmp__()
.
我通常使用 functools.total_ordering 装饰器。
functools.total_ordering(cls) 给定一个定义一个或多个丰富的比较排序方法的类,这个类装饰器提供其余部分。这简化了指定所有可能的丰富比较操作所涉及的工作:
该类必须定义
__lt__()
、__le__()
、__gt__()
或 之一__ge__()
。此外,该类应该提供一个__eq__()
方法。
您应该小心,您的比较方法没有任何副作用。(更改对象的任何值)
对于散列:
你应该实现__hash__()
方法。我认为最好的方法是返回hash(repr(self))
,所以你的哈希是独一无二的。
有几种方法可以将对象标记为可排序。首先 - 丰富的比较,由一组函数定义:
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
模块用于优先级队列。
In addition, I don't like python's design, so many '__ge__', '__gt__', '__le__', '__lt__', '__ne__'
methods are not intuitive at all !
As a contrast, Java's Interface Comparable<T>
(see java doc) returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object, which is direct and friendly!