Home > Mobile >  frozen dataclass with optional attribute
frozen dataclass with optional attribute

Time:01-18

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.

  • Related