我有以下非常简单的数据类:
import dataclasses
@dataclasses.dataclass
class Test:
value: int
我创建了一个类的实例,但是我使用了一个字符串而不是整数:
>>> test = Test('1')
>>> type(test.value)
<class 'str'>
我真正想要的是强制转换为我在类定义中定义的数据类型:
>>> test = Test('1')
>>> type(test.value)
<class 'int'>
我是否必须手动编写__init__
方法,还是有一种简单的方法来实现这一目标?
答案 0 :(得分:5)
使用pydantic.validate_arguments很容易实现
只需在您的数据类中使用 validate_arguments
装饰器:
from dataclasses import dataclass
from pydantic import validate_arguments
@validate_arguments
@dataclass
class Test:
value: int
然后尝试您的演示,'str type' 1 将从 str
转换为 int
>>> test = Test('1')
>>> type(test.value)
<class 'int'>
如果你传递了真正错误的类型,它会引发异常
>>> test = Test('apple')
Traceback (most recent call last):
...
pydantic.error_wrappers.ValidationError: 1 validation error for Test
value
value is not a valid integer (type=type_error.integer)
答案 1 :(得分:4)
从不会强制执行或检查类型的意义上遵守数据类属性的类型提示。大多数情况下,像mypy这样的静态类型检查器都可以完成这项工作,Python在运行时不会这样做,因为它永远不会这样做。
如果要添加手动类型检查代码,请使用__post_init__
方法:
@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)
您可以使用dataclasses.fields(self)
获取一个Field
对象的元组,该对象指定字段和类型,并对其进行循环以自动为每个字段执行此操作,而无需为每个字段单独编写。 / p>
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 :(得分:1)
您可以使用__post_init__
方法来实现:
import dataclasses
@dataclasses.dataclass
class Test:
value : int
def __post_init__(self):
self.value = int(self.value)
此方法被称为__init__
方法
https://docs.python.org/3/library/dataclasses.html#post-init-processing
答案 3 :(得分:0)
是的,简单的答案是自己在自己的__init__()
中进行转换。我这样做是因为我想要我的对象frozen=True
。
对于类型验证,Pydandic声称可以这样做,但是我还没有尝试过:https://pydantic-docs.helpmanual.io/