2010-07-11 67 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