David Dahan
David Dahan

Reputation: 11172

How to make an unfrozen dataclass instance hashable?

When defining a dataclass with frozen=False (default behaviour), and then instantiating an object of this class, is there a way to make this object hashable?

Why do I need this?

Before Python 3.7, I used named tuples instead of dataclasses and I used to find duplicates using set(), but I can't use it anymore. I don't want to use frozen=True on dataclasses for other reasons.

Upvotes: 6

Views: 1843

Answers (1)

user2357112
user2357112

Reputation: 281683

There's a parameter for that:

@dataclass(unsafe_hash=True)
class Whatever:
    ...

You should probably use frozen=True, though. If you need to update attributes on a frozen dataclass instance, you can use dataclasses.replace to construct a new object:

new_thing = dataclasses.replace(old_thing, var=new_val)

You can also use a mutable dataclass instance and dataclasses.astuple to get a tuple when you need something hashable. Watch out, though - astuple has a bunch of weird copying behavior, so you can get behavior like the following:

In [1]: import dataclasses

In [2]: @dataclasses.dataclass
   ...: class Foo:
   ...:     a: object
   ...:     b: object
   ...:     

In [3]: x = object()

In [4]: a = Foo(x, x)

In [5]: b = dataclasses.astuple(a)

In [6]: b[0] is b[1]
Out[6]: False

In [7]: b[0] is x
Out[7]: False

In [8]: a == a
Out[8]: True

In [9]: dataclasses.astuple(a) == dataclasses.astuple(a)
Out[9]: False

Upvotes: 9

Related Questions