2012-06-26 38 views
8

Tôi đang thực hiện một dự án bằng Python (3.2) mà tôi cần so sánh các đối tượng do người dùng xác định. Tôi đã quen với OOP trong Java, nơi người ta sẽ xác định một phương pháp compareTo() trong lớp mà xác định thứ tự tự nhiên của lớp đó, như trong ví dụ dưới đây:Tương đương Python của compareTo của Java()

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; 
    } 
} 

Tôi khá mới đến các lớp học/đối tượng trong Python, vì vậy tôi muốn biết cách "pythonic" để xác định thứ tự tự nhiên của một lớp là gì?

+1

Bạn có nghĩa là giống như [ '__cmp__'] (http : //docs.python.org/reference/datamodel.html#object.__cmp__)? –

Trả lời

10

Bạn có thể triển khai các phương pháp đặc biệt __lt__, __gt__ v.v. để triển khai toán tử mặc định cho các loại tùy chỉnh. Xem thêm về chúng trong số language reference.

Ví dụ:

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) 

Hoặc như đã nói bởi stranac trong các ý kiến, bạn có thể sử dụng total_ordering trang trí để tiết kiệm một số cách gõ:

@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

Bạn cũng có thể chỉ định' __lt__' và '__eq__' và sử dụng trình trang trí' functools.total_ordering'. – stranac

+1

Trong Python 2 '__gt__' là tự động' không __lt__' nếu không được cung cấp (chỉ cần thử nghiệm nó). Kỳ lạ là tài liệu nói khác đi. Có người muốn thử nghiệm nó trên Python 3, có thể là @stranac? – schlamar

+0

Bạn nói đúng, nhưng có thể là tài liệu thực sự chỉ đề cập đến nghịch đảo, nghĩa là 'không (a < b) == (a > = b) '(nơi sau này sẽ tăng ngoại lệ nếu không được xác định), vì vậy tôi đoán nó hoán đổi thông số nếu có thể. – poke

6

Python có chức năng tương tự: __cmp__().

bây giờ tôi thấy bạn đang hỏi về 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).) 

Vì vậy, có vẻ như bạn luôn có thể làm điều gì đó như

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

hoặc

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

sau khi thực hiện __gt__()__lt__().

Mà bạn sau đó sẽ sử dụng như:

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

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

này sẽ cung cấp cho bạn các chức năng tương đương.

+3

'__cmp__' không còn tồn tại trong Python 3, và OP hỏi về Python 3. – poke

Các vấn đề liên quan