16

我正在用 Python (3.2) 做一个项目,我需要比较用户定义的对象。我习惯于使用 Java 中的 OOP,在compareTo()类中定义一个方法来指定该类的自然顺序,如下例所示:

public class Foo {
    int a, b;

    public Foo(int aa, int bb) {
        a = aa;
        b = bb;
    }

    public int compareTo(Foo that) {
        // return a negative number if this < that
        // return 0 if this == that
        // return a positive number if this > that

        if (this.a == that.a) return this.b - that.b;
        else return this.a - that.a;
    }
}

我对Python中的类/对象相当陌生,所以我想知道定义类的自然顺序的“pythonic”方式是什么?

4

2 回答 2

20

您可以实现特殊方法__lt____gt__来实现自定义类型的默认运算符。在语言参考中查看更多关于它们的信息。

例如:

class Foo:
    def __init__ (self, a, b):
        self.a = a
        self.b = b

    def __lt__ (self, other):
        if self.a == other.a:
            return self.b < other.b
        return self.a < other.b

    def __gt__ (self, other):
        return other.__lt__(self)

    def __eq__ (self, other):
        return self.a == other.b and self.b == other.b

    def __ne__ (self, other):
        return not self.__eq__(other)

或者正如评论中的 stranac 所说,您可以使用total_ordering装饰器来节省一些输入:

@functools.total_ordering
class Foo:
    def __init__ (self, a, b):
        self.a = a
        self.b = b

    def __lt__ (self, other):
        if self.a == other.a:
            return self.b < other.b
        return self.a < other.b

    def __eq__ (self, other):
        return self.a == other.b and self.b == other.b
于 2012-06-26T21:05:19.227 回答
6

Python 也有类似的功能:__cmp__().

我现在看到您在询问 Python 3。 他们的“最新消息”建议

cmp() 函数应该被视为消失,而 __cmp__() 特殊方法
不再支持。使用 __lt__() 进行排序,使用 __eq__() 和 __hash__(),以及
根据需要进行其他丰富的比较。(如果你真的需要 cmp() 功能,
您可以使用表达式 (a > b) - (a < b) 作为 cmp(a, b) 的等价物。)

所以看起来你总是可以做类似的事情

def compareTo(self, that):
    return ((self > that) - (self < that))

或者

@classmethod
def compare(cls, a, b):
    return ((a > b) - (a < b))

实施后__gt__()__lt__().

然后你会使用它:

f1 = Foo(1,1)
f2 = Foo(2,2)

f1.compareTo(f2)
Foo.compare(f1,f2)

这将为您提供等效的功能。

于 2012-06-26T21:04:54.033 回答