Создание именованного кортежа с пользовательской хэш-функцией - PullRequest
18 голосов
/ 11 июля 2010

Скажите, у меня есть namedtuple, как это:

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

И я хочу, чтобы для хэширования использовалась следующая функция:

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

Я хочу это, потому что хочу, чтобы порядок item1 и item2 не имел значения (я сделаю то же самое для оператора сравнения). Я думал о двух способах сделать это. Первый будет:

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

Итак, что я могу сделать? Или это вообще плохая идея, и я должен просто написать свой собственный класс с нуля?

1 Ответ

25 голосов
/ 11 июля 2010

Я думаю, что с вашим кодом что-то не так (я предполагаю, что вы создали экземпляр кортежа с тем же именем, поэтому 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
...