【发布时间】:2019-06-26 13:51:49
【问题描述】:
在 Python 3.7 中有这些新的“数据类”容器,它们基本上类似于可变的命名元组。假设我创建了一个代表一个人的数据类。我可以像这样通过__post_init__() 函数添加输入验证:
@dataclass
class Person:
name: str
age: float
def __post_init__(self):
if type(self.name) is not str:
raise TypeError("Field 'name' must be of type 'str'.")
self.age = float(self.age)
if self.age < 0:
raise ValueError("Field 'age' cannot be negative.")
这将使良好的输入通过:
someone = Person(name="John Doe", age=30)
print(someone)
Person(name='John Doe', age=30.0)
虽然所有这些错误的输入都会引发错误:
someone = Person(name=["John Doe"], age=30)
someone = Person(name="John Doe", age="thirty")
someone = Person(name="John Doe", age=-30)
但是,由于数据类是可变的,我可以这样做:
someone = Person(name="John Doe", age=30)
someone.age = -30
print(someone)
Person(name='John Doe', age=-30)
从而绕过输入验证。
那么,在初始化之后,确保数据类的字段不会突变为坏东西的最佳方法是什么?
【问题讨论】:
-
使用
@dataclass(frozen=True)使其“不可变” -
@juanpa.arrivillaga 这首先会破坏使用数据类的目的。如果我想要一个不可变的数据容器,我只会使用一个命名元组。我打算在初始化变量后的某个时间更新字段。
-
好吧,namedtuples 是元组,@dataclass 只是一个装饰器,让您可以跳过编写大量样板来创建经常遇到的类,它不是只是“一个可变的命名元组”。但是我想,您将不得不将您的属性隐藏在
property或其他东西后面,但这会消除数据类的一些优点
标签: python validation python-dataclasses