Search code examples
pythondictionaryhashpython-dataclasses

How can I make a dataclass hash the same as a string?


I want to replace string keys in dictionaries in my code with a dataclass so that I can provide meta data to the keys for debugging. However, I still want to be able to use a string to lookup dictionaries. I tried implementing a data-class with a replaced __hash__ function, however my code is not working as expected:

from dataclasses import dataclass

@dataclass(eq=True, frozen=True)
class Key:
    name: str

    def __hash__(self):
        return hash(self.name)

k = "foo"
foo = Key(name=k)

d = {}
d[foo] = 1

print(d[k])  # Key Error

The two hash functions are the same:

print(hash(k) == hash(foo))  # True

So I don't understand why this doesn't work.


Solution

  • Two objects having different hashes guarantees that they're different, but two objects having the same hash doesn't in itself guarantee that they're the same (because hash collisions exist). If you want the Key to be considered equal to a corresponding str, implement that in __eq__:

        def __eq__(self, other):
            if isinstance(other, Key):
                return self.name == other.name
            if isinstance(other, str):
                return self.name == other
            return False
    

    This fixes the KeyError you're encountering.