After learning a little about dataclasses, it seems that a dataclass will always HAVE all the properties you defined. Adding the Optional
only means that you don't have to pass a param into the constructor. I want to make a field required in the sense that it cannot be None
.
So if I have
@dataclass
class SomeClass():
a: int
b: Optional[int] = None
test = SomeClass(a=None)
I want this to throw an error, but don't know the best way to achieve that result.
Two ideas I have are using the __post_init__
to run validation logic or maybe using pydantic.
Is there a generally accepted solution for this problem?
Both ways you mentioned are quite suitable, but pydantic.dataclasses
will do automatic validation for you:
from typing import Optional
from pydantic.dataclasses import dataclass as pdataclass
@pdataclass
class SomeClass():
a: int
b: Optional[int] = None
test = SomeClass(a=None)
Gives a verbose output/error:
test = SomeClass(a=None)
^^^^^^^^^^^^^^^^^
File "/data/.virtualenvs/test/lib/python3.11/site-packages/pydantic/_internal/_dataclasses.py", line 132, in __init__
s.__pydantic_validator__.validate_python(ArgsKwargs(args, kwargs), self_instance=s)
pydantic_core._pydantic_core.ValidationError: 1 validation error for SomeClass
a
Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]
With standard dataclasses
you'd need to provide your own validation logic within __post_init__
method:
from dataclasses import dataclass
from typing import Optional
@dataclass
class SomeClass():
a: int
b: Optional[int] = None
def __post_init__(self):
if not isinstance(self.a, int):
raise ValueError('Field `a` must be of integer type')
test = SomeClass(a=None)
test = SomeClass(a=None)
^^^^^^^^^^^^^^^^^
File "<string>", line 5, in __init__
..., in __post_init__
raise ValueError('Field `a` must be of integer type')
ValueError: Field `a` must be of integer type