I\'ve been reading up on Python 3.7\'s dataclass as an alternative to namedtuples (what I typically use when having to group data in a structure). I was wondering if datacla
Currently, the best way I found was to overwrite the dataclass fields by property in a separate child class.
from dataclasses import dataclass, field
@dataclass
class _A:
x: int = 0
class A(_A):
@property
def x(self) -> int:
return self._x
@x.setter
def x(self, value: int):
self._x = value
The class behave like a regular dataclass. And will correctly define the __repr__ and __init__ field (A(x=4) instead of A(_x=4). The drawback is that the properties cannot be read-only.
This blog post, tries to overwrite the wheels dataclass attribute by the property of the same name.
However, the @property overwrite the default field, which leads to unexpected behavior.
from dataclasses import dataclass, field
@dataclass
class A:
x: int
# same as: `x = property(x) # Overwrite any field() info`
@property
def x(self) -> int:
return self._x
@x.setter
def x(self, value: int):
self._x = value
A() # `A(x=)` Oups
print(A.__dataclass_fields__) # {'x': Field(name='x',type=,default=,init=True,repr=True}
One way solve this, while avoiding inheritance would be to overwrite the field outside the class definition, after the dataclass metaclass has been called.
@dataclass
class A:
x: int
def x_getter(self):
return self._x
def x_setter(self, value):
self._x = value
A.x = property(x_getter)
A.x = A.x.setter(x_setter)
print(A(x=1))
print(A()) # missing 1 required positional argument: 'x'
It should probably possible to overwrite this automatically by creating some custom metaclass and setting some field(metadata={'setter': _x_setter, 'getter': _x_getter}).