为了使自定义类的对象具有可比性,仅仅定义`__eq__`和`__lt__`系列中的一些成员就足够了吗?

Pee*_*aha 2 python magic-methods python-3.x

比方说,我有一个类,其成员想与通常的运营商比较==,<,<=,>,和>=.

据我所知,这可以通过初始化定义魔术方法来实现,该方法__cmp__(a, b)返回-1(a < b),0(a == b)或1(a > b).

这似乎是__cmp__ 因为Python 3弃用赞成界定__eq__,__lt__,__le__,__gt__,和_ge__单独的方法.

我定义__eq____lt__假设默认值__le__看起来像return a == b or a < b.以下类似乎不是这样的:

class PQItem:
    def __init__(self, priority, item):
        self.priority = priority
        self.item = item

    def __eq__(self, other):
        return isinstance(other, PQItem) and self.priority == other.priority

    def __lt__(self, other):
        return isinstance(other, PQItem) and self.priority < other.priority

class NotComparable:
    pass

x = NotComparable()
y = NotComparable()
# x < y gives error
Run Code Online (Sandbox Code Playgroud)

我得到了这个结果:

>>> PQItem(1, x) == PQItem(1, y)
True
>>> PQItem(1, x) < PQItem(1, y)
False
>>> PQItem(1, x) <= PQItem(1, y)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: PQItem() <= PQItem()
Run Code Online (Sandbox Code Playgroud)

这让我得出结论,我必须手动定义所有的比较魔术方法,以使类可比.有没有更好的方法?

为何__cmp__被弃用?这似乎是一个更好的方法来处理它

blh*_*ing 5

对于两个物体ab,__cmp__要求之一 a < b,a == ba > b是真实的.但是,这可能并非如此:考虑套,它是非常普遍,这些都不是真实的,例如{1, 2, 3}VS {4, 5, 6}.

所以__lt__和喜欢的人一起介绍了.但是这给Python留下了两个独立的排序机制,这有点荒谬,因此在Python 3中删除的灵活性较低.

您实际上不必实现所有六种比较方法.您可以使用functools.total_ordering类装饰器来帮助定义其余的魔术比较方法:

from functools import total_ordering
@total_ordering
class PQItem:
    def __init__(self, priority, item):
        self.priority = priority
        self.item = item

    def __eq__(self, other):
        return isinstance(other, PQItem) and self.priority == other.priority

    def __lt__(self, other):
        return isinstance(other, PQItem) and self.priority < other.priority
Run Code Online (Sandbox Code Playgroud)