2017-02-06 29 views
2

考慮:集包含用戶定義的類中使用__hash__功能

class T: 
    def __hash__(self): 
     return 1234 

t1 = T() 
t2 = T() 

my_set = { t1 } 

我希望下面的打印True

print t2 in my_set 

這不是應該打印True因爲t1t2有相同的散列值。我如何使setin運算符使用給定的散列函數?

+0

t1和t2是不相等的,它們是兩個不同的對象。 – Fallen

回答

2

需要定義一個__eq__方法,因爲僅是相同的情況下a is b或等於a == b(除了具有相同hash)將由setdict被識別爲等於:

class T: 
    def __hash__(self): 
     return 1234 
    def __eq__(self, other): 
     return True 

t1 = T() 
t2 = T() 

my_set = { t1 } 

print(t2 in my_set) # True 

data model on __hash__(和the same documentation page for Python 2 )解釋這一點:

__hash__

由內置函數hash()調用,並用於散列集合的成員操作,包括set,frozensetdict. __hash__()應該返回一個整數。 唯一需要的屬性是比較相等的對象具有相同的散列值;建議將對象組件的哈希值混合在一起,這些哈希值也通過將對象組裝到一個元組中並對元組進行哈希處理來對比對象。

如果一個班級沒有定義__eq__()方法,它不應該定義__hash__()操作;如果它定義了__eq__()而不是__hash__(),則其實例將不可用作可哈希集合中的項目。如果一個類定義了可變對象並實現了一個__eq__()方法,那麼它不應該實現__hash__(),因爲可哈希集合的實現要求密鑰的哈希值是不可變的(如果對象的哈希值更改,它將位於錯誤的哈希桶中)。

默認情況下,用戶定義的類有__eq__()__hash__()方法;與他們,所有的對象比較不平等(除了與他們自己)和x.__hash__()返回一個適當的值,這樣x == y意味着這兩個x is y and hash(x) == hash(y)

(重點煤礦)

注:在Python 2,你還可以實現__cmp__方法,而不是__eq__

0

在僞碼,用於組邏輯.__包含__()當由x in s稱爲大致是:

h = hash(s)       # This uses your class's __hash__() 
i = h % table_size     # This logic is internal to the hash table 
if table[i] is empty: return False # Nothing found in the set 
if table[i] is x: return True  # Identity implies equality 
if hash(table[i]) != h: return False # Hash mismatch implies inequality 
return table[i] == x     # This needs __eq__() in your class