Closed mixilchenko closed 1 year ago
Speaking about dataclasses, InitVar
always looked for me like some crutch when
default
and default_factory
are not enough to define default valueI am not so good with examples but here it is (https://mypy-play.net/?mypy=0.981&python=3.10 launchable)
from dataclasses import dataclass, field, InitVar
from functools import cached_property
@dataclass
class A1:
value: int | str
def __post_init__(self) -> None:
self.value = int(self.value)
@dataclass
class A2:
value: int
def __post_init__(self) -> None:
self.value = int(self.value)
@dataclass
class A3:
arg: InitVar[int | str]
value: int = field(init=False)
def __post_init__(self, arg: int | str) -> None:
self.value = int(arg)
class A4:
arg: int | str
@cached_property
def value(self) -> int:
return int(self.arg)
a1 = A1('2')
reveal_type(a1.value) # Revealed type is "Union[builtins.int, builtins.str]"
a2 = A2('2') # Argument 1 to "A2" has incompatible type "str"; expected "int"
reveal_type(a2.value) # Revealed type is "builtins.int"
a3 = A3('2')
reveal_type(a3.value) # Revealed type is "builtins.int"
a4 = A4('2')
reveal_type(a4.value) # Revealed type is "builtins.int"
In that case, A3
is preferred over A4
for me because arg
is not saved inside
Speaking about argument parser, I don't think that any additional marks are needed. InitVar
s do look like usual __init__
arguments and that seems totally reasonable for me.
Wow, really interesting stuff @mixilchenko ! I'll do a proper review soon!