2011-07-14 55 views
1

我需要設計支持某種不確定性(或者野性字符,如果願意的話)它的組件的對象。 這項工作是在Python中完成的。散列不確定對象

考慮下面的類

class C(): 
    def __init__(self, p1): 
     self.p1 = p1 

屬性p1可以是 「X」, 「Y」, 「Z」,但有時 「X或Y」,或任何其他組合。

它是必需的是,如果c1p1是 'x' 和的c2p1是 'x或y',則c1 == c2將返回True。通過提供合適的__eq__功能可輕鬆實現此功能。 但是,這些對象也需要存儲在一個集合中,因此我需要提供一個__hash__函數。 你會如何計算這種情況下的散列函數,例如c1 == c2,然後hash(c1) == hash(c2)

選項1:散列屬性

不好這也是爲什麼

c1 = C('x') 
c2 = C('x or y or z') 
c1 == c2 #True 
hash(c1) == hash(c2)#False 
+0

對不起,我沒有完全讀你的問題(和'選項1'應該真的是我的回答評論)。更新了我的答案。 – phihag

+0

我認爲你不應該爲此使用平等。 – katrielalex

回答

1

你平等的準則是不可傳遞的,因此無效:

C('x') == C('x or y') == C('y') 

C('x') != C('y') 

既然你可以構建等於其他所有C('x or y or z or a or ...')的元素,即滿足C1唯一的哈希函數== C2⇒哈希(C1)==哈希(C2)是永恆的,即

def __hash__(self): 
    return 0 
0

我有隻是意識到我的設計要求是錯誤的。 C('x')== C('x或y')爲True並且C('y')== C('x或y')爲True的要求也將要求C('x ')== C('y')也將爲True。看起來我需要重新思考我的設計,並可能放棄擁有對象哈希的能力。你怎麼看?

+1

我認爲這應該是對原始問題的評論或補充;)。 – phihag

0

它是必需的是,如果c1p1是 'x' 和的c2p1是 'x或y',則c1 == c2將返回True

這很粗略(即可能很糟糕)的設計。平等應該是傳遞性的,所以如果c1 == c2c2 == c3,那麼c1 == c3。現在,您的規範要求C('x') == C('x or y')C('x or y') == C('y'),這應該暗示C('x') == C('y') - 但您可能不希望這是真實的。 (而且我看到你在寫這篇文章的時候就明白了這一點。)

我建議你離開__eq__單獨使用一種完全不同的方法來執行這些「模糊」比較,或許就像is_compatible_with。或者如果你要重新實現__eq__,至少要讓它遵循傳遞屬性是明智的,比如只是比較字符串參數。這可能意味着__eq__對於您的特定應用程序並不是非常有用,但這沒關係;這就是爲什麼你可以創建其他方法。

0

最簡單的解決方案是讓所有對象返回相同的散列。由於包含的對象將全部插入到相同的插槽中,因此這會將設置的O(1)性能降低到O(n)。然後使用__eq__方法進行判別。

關於您的要求,David已經廣泛回答。