2010-07-11 8 views
13

Nói rằng tôi có một namedtuple như thế này:Tạo một namedtuple với một chức năng tùy chỉnh băm

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

Và tôi muốn các chức năng sau đây được sử dụng để băm:

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

Tôi muốn điều này vì tôi muốn thứ tự của item1item2 không liên quan (tôi sẽ làm tương tự cho toán tử so sánh). Tôi nghĩ về hai cách để làm điều này. Đầu tiên sẽ là:

FooTuple.__hash__ = foo_hash 

Tác phẩm này, nhưng nó bị tấn công. Vì vậy, tôi đã cố gắng subclassing FooTuple:

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

    # custom hash function here 

Nhưng sau đó tôi nhận được điều này:

DeprecationWarning: object.__init__() takes no parameters 

Vì vậy, những gì tôi có thể làm gì? Hay đây là một ý tưởng tồi hoàn toàn và tôi chỉ nên viết lớp của riêng tôi từ đầu?

Trả lời

18

Tôi nghĩ rằng có gì đó sai với mã của bạn (tôi đoán là bạn đã tạo một thể hiện của tuple có cùng tên, vì vậy fooTuple bây giờ là một bộ tuple, không phải là một lớp tuple), bởi vì phân lớp tuple có tên như vậy nên làm việc. Dù sao, bạn không cần phải xác định lại hàm tạo. Bạn chỉ có thể thêm hàm băm:

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

Cảm ơn, chỉ cần thoát khỏi hàm tạo trong phân lớp đã khắc phục được sự cố. –

+11

Lưu ý rằng 'repr (foo)' sẽ vẫn nói về 'Foo'. Điều này có thể được thực hiện tốt hơn như 'class Foo (namedtuple ('Foo', ['item1', 'item2'], verbose = False)):' –

+0

chú ý đến câu trả lời của @ Sven [ở đây] (http: // stackoverflow. com/questions/4901815/object-of-custom-type-as-dictionary-key) –