问题
I have the following very simple dataclass:
import dataclasses
@dataclasses.dataclass
class Test:
value: int
I create an instance of the class but instead of an integer I use a string:
>>> test = Test('1')
>>> type(test.value)
<class 'str'>
What I actually want is a forced conversion to the datatype i defined in the class defintion:
>>> test = Test('1')
>>> type(test.value)
<class 'int'>
Do I have to write the __init__
method manually or is there a simple way to achieve this?
回答1:
The type hint of dataclass attributes is never obeyed in the sense that types are enforced or checked. Mostly static type checkers like mypy are expected to do this job, Python won't do it at runtime, as it never does.
If you want to add manual type checking code, do so in the __post_init__ method:
@dataclasses.dataclass
class Test:
value: int
def __post_init__(self):
if not isinstance(self.value, int):
raise ValueError('value not an int')
# or self.value = int(self.value)
You could use dataclasses.fields(self) to get a tuple of Field objects which specify the field and the type and loop over that to do this for each field automatically, without writing it for each one individually.
def __post_init__(self):
for field in dataclasses.fields(self):
value = getattr(self, field.name)
if not isinstance(value, field.type):
raise ValueError(f'Expected {field.name} to be {field.type}, '
f'got {repr(value)}')
# or setattr(self, field.name, field.type(value))
回答2:
You could achieve this using the __post_init__
method:
import dataclasses
@dataclasses.dataclass
class Test:
value : int
def __post_init__(self):
self.value = int(self.value)
This method is called following the __init__
method
https://docs.python.org/3/library/dataclasses.html#post-init-processing
回答3:
Yeah, the easy answer is to just do the conversion yourself in your own __init__()
. I do this because I want my objects frozen=True
.
For the type validation, Pydandic claims to do it, but I haven't tried it yet: https://pydantic-docs.helpmanual.io/
来源:https://stackoverflow.com/questions/54863458/force-type-conversion-in-python-dataclass-init-method