I'm trying create frozen dataclass with optional attribute is_complete
:
from dataclass import dataclass
from typing import Optional
@dataclass(frozen=True)
class MyHistoricCandle:
open: float
high: float
low: float
close: float
volume: int
time: datetime
is_complete: Optional[bool]
But when i init MyHistoricCandle
object without is_complete
attribute:
MyHistoricCandle(open=1, high=1, low=1, close=1, volume=1, time=datetime.now())
Getting this error:
TypeError: MyHistoricCandle.__init__() missing 1 required positional argument: 'is_complete'
Question: Is it even possible to create frozen dataclass with optional attribute? I tried
is_complete: Optional[bool] = None
, but sometimes i don't want add this field instead of setting None
value
CodePudding user response:
By using dataclass
, you are committing to a certain level of rigor regarding the interface to your class. All instances of MyHistoricCandle
should have an is_complete
attribute, not just some. If you don't want that to be the case, you should probably define two separate classes, one with the attribute and one without.
But, you can work around it by not declaring is_complete
as a *field, but as an explicit attribute initialized by an init-only variable with a default value of
None`.
from dataclasses import dataclass, InitVar
@dataclass(frozen=True)
class MyHistoricCandle:
open: float
high: float
low: float
close: float
volume: int
time: datetime
is_complete: InitVar[Optional[bool]] = None
def __post_init_(self, is_complete):
if is_complete is not None:
self.is_complete = is_complete
As is_complete
is not a field, it will be your responsibility to override any of the autogenerated methods (__repr__
, __eq__
, etc) to take into account the value of self.is_complete
.
CodePudding user response:
TL;DR The type does not make an attribute optional; the presence of a default value does.
dataclass
doesn't use the specified type for anything*, much less infer a default value for the field if you don't supply an argument when constructing the value. If you want to omit is_complete
from the call, you need to specify what value should be used in its place, whether that value be True
, False
, or None
.
@dataclass(frozen=True) class MyHistoricCandle: open: float high: float low: float close: float volume: int time: datetime is_complete: Optional[bool] = None
* With the exception of InitVar
and ClassVar
.