2012-06-26 64 views
8

我正在做一個Python(3.2)項目,我需要比較用戶定義的對象。我已經習慣了在Java中,OOP的其中一個將定義指定該類的自然排序的一類方法compareTo(),如下面的例子:Python的等價Java的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」方法來定義類的自然排序?

+1

你的意思是像['__cmp__'](HTTP ://docs.python.org/reference/datamodel.html#object.__cmp__)? –

回答

10

您可以實現特殊方法__lt__,__gt__等來實現自定義類型的默認運算符。在language reference中查看更多關於它們的信息。

例如:

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 
+3

您也可以定義'__lt__'和'__eq__'並使用'functools.total_ordering'修飾符。 – stranac

+1

在Python 2中,'__gt__'如果沒有提供(僅僅測試它),會自動爲'not __lt__'。奇怪的是,文件說,否則。有人想在Python 3上測試它,也許@stranac? – schlamar

+0

你是對的,但它可能是文件實際上只涉及反例,即'不((< b) == (a > = b)'(後者會引發一個異常,如果沒有定義),所以我想它會交換參數如果可能。 – poke

6

Python有一個類似的功能:__cmp__()

我現在看到你問關於Python 3 Their "whats new" suggests

 
The cmp() function should be treated as gone, and the __cmp__() special method 
is no longer supported. Use __lt__() for sorting, __eq__() with __hash__(), and 
other rich comparisons as needed. (If you really need the cmp() functionality, 
you could use the expression (a > b) - (a < b) as the equivalent for 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) 

這會給你相當的功能。

+3

'__cmp__'在Python 3中不再存在,並且OP在詢問Python 3. – poke