from dataclasses import dataclass
@dataclass
class coordinate:
x: int
y: int
objects = {}
pos = coordinate(0, 0)
objects[pos] = "A"
pos.x += 1 # Changing the current position I am looking at
objects[pos] = "B"
pos.y += 1
objects[pos] = "C"
for position in objects:
print(position, objects[position])
This throws TypeError: unhashable type: 'coordinate'
.
Setting @dataclass(frozen=True, eq=True)
throws dataclasses.FrozenInstanceError: cannot assign to field 'x'
.
And finally, using @dataclass(unsafe_hash=True)
results in:
coordinate(x=1, y=1) C
coordinate(x=1, y=1) C
coordinate(x=1, y=1) C
One way way to do this is to use objects[(pos.x, pos.y)]
, but that just seems to defeat the purpose of using the dataclass in the first place. Is there a better, more pythonic way of doing this?
dict
keys should be immutable objects, so frozen=True
is non-negotiable.
To "modify" a frozen object, you need to make a copy of it. The dataclasses
module provides a convenience function for that, replace
.
from dataclasses import dataclass, replace
@dataclass(frozen=True)
class coordinate:
x: int
y: int
objects = {}
pos = coordinate(0, 0)
objects[pos] = "A"
pos = replace(pos, x=pos.x+1) # Changing the current position I am looking at
objects[pos] = "B"
pos = replace(pos, y=pos.y+1)
objects[pos] = "C"
for position in objects:
print(position, objects[position])