I have a question about best practices when it comes to python dataclasses. The dataclass structure. Is it OK practice to delete temporary class attributes, or am I better off foregoing the dataclass entirely?
I want to use the attribute IOMap (name suggestions welcome) to represent the flow through a factory, where the inputs have a negative rate and the outputs have a positive rate. However, I know that my users will probably be thinking in terms of inputs and outputs, so I want to give them the option to construct the class that way.
There are two ways to do this. This is the traditional approach:
class Factory(Building):
def __init__(self,
*,
id: str,
name: str,
power: int,
size: int,
inputs: Dict[Material, float] = None,
outputs: Dict[Material, float] = None,
IOMap: Dict[Material, float] = None,
):
super().__init__(id, name, power, size)
if IOMap is not None:
if inputs is not None or outputs is not None:
raise ValueError("IOMap cannot be used with inputs or outputs.")
self.IOMap = IOMap
else:
if inputs is None or outputs is None:
raise ValueError("inputs and outputs must be provided if IOMap is not.")
self.IOMap = outputs
for material, rate in inputs.items():
self.IOMap[material] = self.IOMap.get(material, 0) - rate
And this is the dataclass approach:
@dataclass
class Factory(Building):
inputs: Optional[Dict[Material, float]] = None
outputs: Optional[Dict[Material, float]] = None
IOMap: Optional[Dict[Material, float]] = None
def __post_init__(self):
if IOMap is not None:
if inputs is not None or outputs is not None:
raise ValueError("IOMap cannot be used with inputs or outputs.")
self.IOMap = IOMap
else:
if inputs is None or outputs is None:
raise ValueError("inputs and outputs must be provided if IOMap is not.")
self.IOMap = outputs
for material, rate in inputs.items():
self.IOMap[material] = self.IOMap.get(material, 0) - rate
del self.inputs
del self.outputs
I like this much better, but deleing them in this way just feels… wrong.
I don’t want inputs
and outputs
to be class attributes. Since IOMap will be used exclusively for internal processes, I don’t want users thinking that they can use inputs
and outputs
at all.
I would love to continue to use dataclasses, since Factory
is the parent of many children, and it would be amazing not to have to write a monstrous __init__
function for every one.
tldr; Is it worth deleting class attributes to continue to use dataclasses, or is it better to move to a traditional class?