2010-07-11 58 views
13

說我有一個namedtuple這樣的namedtuple:創建一個自定義的哈希函數

FooTuple = namedtuple("FooTuple", "item1, item2") 

,我想用於散列以下功能:

foo_hash(self): 
    return hash(self.item1) * (self.item2) 

我想這是因爲我希望item1item2的順序是不相關的(我會爲比較運算符做同樣的事情)。我想到了兩種方法來做到這一點。第一個將是:

FooTuple.__hash__ = foo_hash 

這可行,但感覺被黑了。於是,我試着子類FooTuple

class EnhancedFooTuple(FooTuple): 
    def __init__(self, item1, item2): 
     FooTuple.__init__(self, item1, item2) 

    # custom hash function here 

但後來我得到這個:

DeprecationWarning: object.__init__() takes no parameters 

那麼,我該怎麼辦?或者這完全是一個壞主意,我應該從頭開始寫我自己的課程?

回答

18

我認爲你的代碼出了問題(我的猜測是你創建了一個具有相同名稱的元組實例,所以fooTuple現在是一個元組,而不是一個元組類),因爲這樣命名的元組的子類化應該管用。無論如何,你不需要重新定義構造函數。您可以添加散列函數:

In [1]: from collections import namedtuple 

In [2]: Foo = namedtuple('Foo', ['item1', 'item2'], verbose=False) 

In [3]: class ExtendedFoo(Foo): 
    ...:  def __hash__(self): 
    ...:   return hash(self.item1) * hash(self.item2) 
    ...: 

In [4]: foo = ExtendedFoo(1, 2) 

In [5]: hash(foo) 
Out[5]: 2 
+0

謝謝,只是將構造函數留在子類中解決了這個問題。 – 2010-07-11 13:54:10

+11

請注意'repr(foo)'仍然會說'Foo'。這可以做得更好,因爲'class Foo(namedtuple('Foo',['item1','item2'],verbose = False)):' – 2011-10-19 01:31:25

+0

注意@Sven的回答[here](http:// stackoverflow。 COM /問題/ 4901815 /對象的定製型作爲詞典鍵) – 2015-06-22 05:35:17