【问题标题】:Define class attribute for all comparisons为所有比较定义类属性
【发布时间】:2021-08-18 18:08:04
【问题描述】:

我有一个这样的 Python 类:

@dataclass
class Person:
    name: str
    relatives: Iterable['Person']

我想对所有比较使用name 属性,以便Person 对象默认按字母顺序排序。因此,我像这样覆盖__gt__() 方法(如the documentation 中所述):

    def __gt__(self, other):
        return self.name > other.name

这实际上解决了我的初始任务,我可以这样做:

p1=Person("test1", relatives=[])
p2=Person("test2", relatives=[])
sorted([p1, p2])
Out[4]: [Person(name='test1', relatives=[]), Person(name='test2', relatives=[])]

还有这个:

p1>p2
Out[5]: False
p1<p2
Out[6]: True

我明白我不必实现所有运算符:

__lt__() 和 __gt__() 是彼此的反射,__le__() 和 __ge__() 是彼此的反射,__eq__() 和 __ne__() 是自己的反射。

但是,对于相等比较,我仍然必须明确覆盖 __eq__(other)

    def __eq__(self, other):
        return isinstance(other, Person) and self.name == other.name

有没有办法以更简洁的方式实现这一点?我想用某种方式告诉解释器“使用属性name 进行所有比较!”。

【问题讨论】:

    标签: python oop operator-overloading comparator


    【解决方案1】:

    如果在您的情况下提供 __eq__ 并且至少 1 个丰富的比较是可以的,您可以使用 functools.total_ordering 装饰器,如下所示:

    import functools
    @functools.total_ordering
    class Name:
        def __init__(self, name):
            self.name = name
        def __repr__(self):
            return self.name
        def __eq__(self, other):
            return self.name == other.name
        def __gt__(self, other):
            return self.name > other.name
    a = Name("a")
    b = Name("b")
    print(a<b)
    print(a<=b)
    print(b>=a)
    

    输出

    True
    True
    True
    

    如果这在你的情况下不可接受,你需要准备自己的装饰器来使用,关于装饰类的讨论见How to decorate a class

    【讨论】:

    • 太好了,这个装饰器看起来正是我一直在寻找的!我的 IDE (PyCharm) 仍然声称该对象没有实现 SupportsLessThanT,例如 min(p1, p1),但这可能是 PyCharm 而不是 Python 问题。
    猜你喜欢
    • 1970-01-01
    • 2010-12-15
    • 2012-06-14
    • 1970-01-01
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    相关资源
    最近更新 更多