2010-09-09 30 views
5

Nếu tôi hiểu chính xác, hàm __cmp __() của đối tượng được gọi để đánh giá tất cả các đối tượng trong bộ sưu tập trong khi xác định xem đối tượng có phải là thành viên hay 'in' hay không. Tuy nhiên, điều này dường như không phải là trường hợp cho bộ:Tìm hiểu thành viên đối tượng trăn cho các bộ

class MyObject(object): 
    def __init__(self, data): 
     self.data = data 

    def __cmp__(self, other): 
     return self.data-other.data 

a = MyObject(5) 
b = MyObject(5) 

print a in [b]   //evaluates to True, as I'd expect 
print a in set([b])  //evaluates to False 

thế nào là một thành viên đối tượng thử nghiệm trong một bộ, sau đó?

Trả lời

2
>>> xs = [] 
>>> set([xs]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: unhashable type: 'list' 

Hiện tại bạn đang ở đây. Bộ sử dụng băm, rất giống với dicts. Hiệu năng trợ giúp này rất cao (các test thành viên là O (1), và nhiều thao tác khác phụ thuộc vào kiểm tra thành viên), và nó cũng phù hợp với ngữ nghĩa của các bộ: Thiết lập các mục phải là duy nhất, và các mục khác nhau sẽ tạo ra các băm khác nhau, cho biết (tốt, trong lý thuyết) trùng lặp.

Kể từ khi mặc định __hash__ chỉ là id (đó là IMHO khá ngu ngốc), hai trường hợp của một lớp kế thừa object 's __hash__ sẽ không bao giờ băm với giá trị tương tự (tốt, trừ khi không gian địa chỉ lớn hơn sizeof băm).

0

Tập hợp sử dụng dict đằng sau hậu trường, do đó câu lệnh "in" đang kiểm tra xem đối tượng có tồn tại như một khóa trong dict hay không. Vì đối tượng của bạn không thực hiện hàm băm, hàm băm mặc định cho các đối tượng sử dụng id của đối tượng. Vì vậy, mặc dù a và b là tương đương, chúng không phải là cùng một đối tượng, và đó là những gì đang được thử nghiệm.

5

Thêm một phương pháp __hash__ đến lớp học của bạn mang lại điều này:

class MyObject(object): 
    def __init__(self, data): 
     self.data = data 

    def __cmp__(self, other): 
     return self.data - other.data 

    def __hash__(self): 
     return hash(self.data) 


a = MyObject(5) 
b = MyObject(5) 

print a in [b] # True 
print a in set([b]) # Also True! 
+0

Đó chính xác là những gì tôi đang tìm kiếm. Cảm ơn :) – jifa

+0

Mặc dù điều đó nên đọc một cách tự động 'return hash (self.data)'. – delnan

+0

// Đồng thời - để phát hiện thói quen bình luận không phải python của tôi. – jifa

1

Như những người khác chỉ, đối tượng của bạn không có một __hash__ để họ sử dụng id mặc định như một băm, và bạn có thể ghi đè lên nó như Nathon được đề xuất, NHƯNG đọc the docs about __hash__, đặc biệt là các điểm về thời điểm bạn nên và không nên làm điều đó.

+0

đọc chúng sau câu trả lời trước - công cụ tốt :) – jifa

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