2010-10-15 7 views
57

Tôi cần phải tạo đối tượng hoặc lớp 'container' trong Python, giữ một bản ghi các đối tượng khác mà tôi cũng xác định. Một yêu cầu của container này là nếu hai đối tượng được coi là giống nhau, một (hoặc một) được loại bỏ. Suy nghĩ đầu tiên của tôi là sử dụng set([]) làm đối tượng chứa, để hoàn thành yêu cầu này.Làm thế nào để một bộ Python ([]) kiểm tra xem hai đối tượng có bằng nhau không? Phương thức nào cần phải xác định để tùy chỉnh điều này?

Tuy nhiên, bộ này không xóa một trong hai trường hợp đối tượng giống nhau. Tôi phải xác định điều gì để tạo một tài khoản?

Đây là mã Python.

class Item(object): 
    def __init__(self, foo, bar): 
    self.foo = foo 
    self.bar = bar 
    def __repr__(self): 
    return "Item(%s, %s)" % (self.foo, self.bar) 
    def __eq__(self, other): 
    if isinstance(other, Item): 
     return ((self.foo == other.foo) and (self.bar == other.bar)) 
    else: 
     return False 
    def __ne__(self, other): 
    return (not self.__eq__(other)) 

Interpreter

>>> set([Item(1,2), Item(1,2)]) 
set([Item(1, 2), Item(1, 2)]) 

Rõ ràng là __eq__(), được gọi là bởi x == y, không phải là phương pháp được gọi bằng các thiết lập. Cái gì được gọi? Tôi phải định nghĩa phương pháp nào khác?

Lưu ý: CácItems phải vẫn có thể thay đổi, và có thể thay đổi, vì vậy tôi không thể cung cấp một phương pháp__hash__(). Nếu đây là cách duy nhất để làm điều đó, sau đó tôi sẽ viết lại để sử dụng bất biến Item s.

+1

Có cùng vấn đề này. Tôi cho rằng bạn đang thao tác một lượng nhỏ dữ liệu bên trong mã của bạn. Đây có lẽ không phải là một ứng cử viên tốt cho việc sử dụng một cơ sở dữ liệu. Tôi nhớ có thể tạo một tập hợp và xác định một hàm so sánh trong C++ và tôi tin rằng Java là tốt, tuy nhiên nó không giống như bạn có thể làm điều này với các đối tượng từ điển trong Python. Có vẻ như ai đó có thể đã viết một thư viện "set" bằng Python có thể làm điều này, nhưng tôi không biết một. –

Trả lời

22

Tôi sợ bạn sẽ phải cung cấp phương thức __hash__(). Nhưng bạn có thể mã nó theo cách, rằng nó không phụ thuộc vào các thuộc tính có thể thay đổi của Item của bạn.

+1

Trong đoạn thứ hai ở đây, nó chỉ ra rằng '__hash __()' chỉ nên được định nghĩa cho các đối tượng bất biến. – Ada

+1

@Nathanael: nếu đối tượng có thể phải thay đổi, bạn có thể tạo một bản sao bất biến của đối tượng, như frozenset() và set(). –

+2

@Nathanael - bạn muốn gọi '__eq__' như thế nào? So sánh các thuộc tính (1,2) đó? Sau đó, bạn phải trả về một số băm (1,2) cũng trong phương thức '__hash__' của bạn. – eumiro

50

Có, bạn cần __hash__() -method VÀ toán tử so sánh mà bạn đã cung cấp.

class Item(object): 
    def __init__(self, foo, bar): 
     self.foo = foo 
     self.bar = bar 
    def __repr__(self): 
     return "Item(%s, %s)" % (self.foo, self.bar) 
    def __eq__(self, other): 
     if isinstance(other, Item): 
      return ((self.foo == other.foo) and (self.bar == other.bar)) 
     else: 
      return False 
    def __ne__(self, other): 
     return (not self.__eq__(other)) 
    def __hash__(self): 
     return hash(self.__repr__())