Search code examples
pythonhashtablepython-dataclasses

Error: unhashable type: 'dict' with @dataclass


I have a class Table:

@dataclass(frozen=True, eq=True)
class Table:
    name: str
    signature: Dict[str, Type[DBType]]
    prinmary_key: str
    foreign_keys: Dict[str, Type[ForeignKey]]
    indexed: List[str]

And need to create such dictionary:


table = Table(*args)
{table: 'id'}

TypeError: unhashable type: 'dict'

Don't understand what's the problem.


Solution

  • The autogenerated hash method isn't safe, since it tries to hash the unhashable attributes signature, primary_key, and indexed. You need to define your own __hash__ method that ignores those attributes. One possibility is

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

    Both self.name and self.primary_key are immutable, so a tuple containing those values is also immutable and thus hashable.


    An alternative to defining this method explicitly would be to use the field function to turn off the mutable fields for hashing purposes.

    @dataclass(frozen=True, eq=True)
    class Table:
        name: str
        signature: Dict[str, Type[DBType]] = field(compare=False)
        prinmary_key: str
        foreign_keys: Dict[str, Type[ForeignKey]] = field(compare=False)
        indexed: List[str] = field(compare=False)
    

    field has a hash parameter whose default value is the value of compare, and the documentation discourages using a different value for hash. (Probably to ensure that equal items hash identically.) It's unlikely that you really want to use these three fields for the purposes of comparing two tables, so you this should be OK.

    I would consult the documentation rather than relying on my relatively uninformed summary of it.