最佳答案
Python 3.7已经发布了一段时间,我想测试一些新颖的 dataclass
+ 类型特性。使用本机类型和来自 typing
模块的类型获得正确工作的提示非常容易:
>>> import dataclasses
>>> import typing as ty
>>>
... @dataclasses.dataclass
... class Structure:
... a_str: str
... a_str_list: ty.List[str]
...
>>> my_struct = Structure(a_str='test', a_str_list=['t', 'e', 's', 't'])
>>> my_struct.a_str_list[0]. # IDE suggests all the string methods :)
但是我想尝试的另一件事情是在运行时强制类型提示作为条件,也就是说,不可能存在具有不正确类型的 dataclass
。它可以很好地与 __post_init__
一起实现:
>>> @dataclasses.dataclass
... class Structure:
... a_str: str
... a_str_list: ty.List[str]
...
... def validate(self):
... ret = True
... for field_name, field_def in self.__dataclass_fields__.items():
... actual_type = type(getattr(self, field_name))
... if actual_type != field_def.type:
... print(f"\t{field_name}: '{actual_type}' instead of '{field_def.type}'")
... ret = False
... return ret
...
... def __post_init__(self):
... if not self.validate():
... raise ValueError('Wrong types')
这种 validate
函数适用于本机类型和自定义类,但不适用于 typing
模块指定的类:
>>> my_struct = Structure(a_str='test', a_str_list=['t', 'e', 's', 't'])
Traceback (most recent call last):
a_str_list: '<class 'list'>' instead of 'typing.List[str]'
ValueError: Wrong types
有没有更好的方法用 typing
类型的列表来验证非类型化列表?最好不包括检查任何 list
、 dict
、 tuple
或 set
中属于 dataclass
’属性的所有元素的类型。
几年后再回到这个问题,在需要验证通常只定义数据类的类的情况下,我现在转而使用 pydantic
。我会留下我的印记与目前接受的答案,因为它正确地回答了原来的问题,并具有突出的教育价值。