Создание именованного элемента с пользовательской хэш-функцией
Скажем, у меня есть 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
Я думаю, что что-то не так с вашим кодом (я предполагаю, что вы создали экземпляр кортежа с тем же именем, поэтому 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
Ответ 2
Начиная с Python 3.6.1, это может быть достигнуто более просто с помощью класса typing.NamedTuple
(при условии, что вы в порядке с подсказками типов):
from typing import NamedTuple, Any
class FooTuple(NamedTuple):
item1: Any
item2: Any
def __hash__(self):
return hash(self.item1) * hash(self.item2)