2010-09-09 56 views
5

如果我理解正確,則會調用對象的__cmp __()函數,以便在確定對象是成員還是集合中的「in」時評估集合中的所有對象。 然而,這似乎並沒有成爲套的情況:瞭解集合的Python對象成員資格

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 

如何對象的成員在一組測試,然後呢?

回答

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

你在那裏。設置使用散列,非常類似於字典。這極大地幫助了性能(成員測試是O(1),許多其他操作依賴於成員測試),並且它也適合集的語義:設置項必須是唯一的,並且不同的項會生成不同的哈希值,而同一哈希表明(理論上)重複。

由於默認__hash__只是id(這是相當笨IMHO),繼承object__hash__永遠散列爲相同的值(當然,除非尋址空間大於sizeof散列大的類的兩個實例)。

0

一個集合在後臺使用字典,因此「in」語句檢查對象是否作爲字典中的鍵存在。由於你的對象沒有實現散列函數,因此對象的默認散列函數使用該對象的ID。所以即使a和b是等價的,它們也不是同一個對象,這就是測試的結果。

5

添加__hash__方法,類產生這樣的:

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

這正是我所期待的。謝謝:) – jifa 2010-09-09 18:47:08

+0

雖然這應該有意識地閱讀'返回哈希(self.data)'。 – delnan 2010-09-09 18:47:56

+0

//另外 - 用於發現我的非python原生評論習慣。 – jifa 2010-09-09 18:48:19

1

正如有人指出,你的對象沒有一個__hash__所以他們使用默認的id作爲一個哈希,你可以重寫它作爲納通建議,但是the docs about __hash__,特別是關於什麼時候你應該和不應該這樣做的觀點。

+0

在之前的回答之後閱讀它們 - 好東西:) – jifa 2010-09-09 19:10:51