Dynamically add fields to dataclass objects
You could use make_dataclass
to create X
on the fly:
X = make_dataclass('X', [('i', int), ('s', str)])x = X(i=42, s='text')asdict(x)# {'i': 42, 's': 'text'}
Or as a derived class:
@dataclassclass X: i: intx = X(i=42)x.__class__ = make_dataclass('Y', fields=[('s', str)], bases=(X,))x.s = 'text'asdict(x)# {'i': 42, 's': 'text'}
As mentioned, fields marked as optional should resolve the issue. If not, consider using properties in dataclasses
. Yep, regular properties should work well enough - though you'll have to declare field in __post_init__
, and that's slightly inconvenient.
If you want to set a default value for the property so accessing getter immediately after creating the object works fine, and if you also want to be able to set a default value via constructor, you can make use of a concept called field properties; a couple libraries like dataclass-wizard providefull support for that.
example usage:
from dataclasses import asdict, dataclassfrom typing import Optionalfrom dataclass_wizard import property_wizard@dataclassclass X(metaclass=property_wizard): i: int s: Optional[str] = None @property def _s(self): return self._s @_s.setter def _s(self, s: str): self._s = sx = X(i=42)x.s = 'text'x# X(i=42, s='text')x.s# 'text'asdict(x)# {'i': 42, 's': 'text'}
Disclaimer: I am the creator (and maintener) of this library.