Force type conversion in python dataclass __init__ method

前端 未结 3 1902
孤城傲影
孤城傲影 2021-01-07 20:43

I have the following very simple dataclass:

import dataclasses

@dataclasses.dataclass
class Test:
    value: int

I create an instance of t

相关标签:
3条回答
  • 2021-01-07 21:26

    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))
    
    0 讨论(0)
  • 2021-01-07 21:32

    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

    0 讨论(0)
  • 2021-01-07 21:38

    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/

    0 讨论(0)
提交回复
热议问题