Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a namedtuple with a custom hash function

Tags:

Say I have a namedtuple like this:

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

And I want the following function to be used for hashing:

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

I want this because I want the order of item1 and item2 to be irrelevant (I will do the same for the comparison-operator). I thought of two ways to do this. The first would be:

FooTuple.__hash__ = foo_hash 

This works, but it feels hacked. So I tried subclassing FooTuple:

class EnhancedFooTuple(FooTuple):     def __init__(self, item1, item2):         FooTuple.__init__(self, item1, item2)      # custom hash function here 

But then I get this:

DeprecationWarning: object.__init__() takes no parameters 

So, what can I do? Or is this a bad idea altogether and I should just write my own class from scratch?

like image 709
Björn Pollex Avatar asked Jul 11 '10 13:07

Björn Pollex


People also ask

What is the difference between Namedtuple and dictionary?

Python Namedtuple vs Dict – Difference explainedPython namedtuples are immutable while a dictionary is mutable in python. A namedtuple can be used to access elements in the tuple using the names and not just the indexes while the data in a python dict can be accessed using a key:value pairing.

Can Namedtuple be pickled?

@Antimony: pickle handles namedtuple classes just fine; classes defined in a function local namespace not so much.

Is Namedtuple fast?

NamedTuple is the faster one while creating data objects (2.01 µs). An object is slower than DataClass but faster than NamedTuple while creating data objects (2.34 µs).


1 Answers

I think there is something wrong with your code (my guess is that you created an instance of the tuple with the same name, so fooTuple is now a tuple, not a tuple class), because subclassing the named tuple like that should work. Anyway, you don't need to redefine the constructor. You can just add the hash function:

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 
like image 99
Lukáš Lalinský Avatar answered Oct 01 '22 11:10

Lukáš Lalinský