[英]Subclass of dataclass, with some assertions
我有一个保存数据的冻结数据类MyData
。 我想要一个杰出的子类MySpecialData
只能保存长度为 1 的数据。这是一个有效的实现。
from dataclasses import dataclass, field
@dataclass(frozen=True)
class MyData:
id: int = field()
data: list[float] = field()
def __len__(self) -> int:
return len(self.data)
@dataclass(frozen=True)
class MySpecialData(MyData):
def __post_init__(self):
assert len(self) == 1
# correctly throws exception
special_data = MySpecialData(id=1, data=[2, 3])
我花了一些时间弄乱__new__
和__init__
,但无法找到可行的解决方案。 该代码有效,但我是一个新手,如果这是完成此任务的“正确”方式,我正在征求有经验的人的意见。 任何关于如何更好或更正确地做到这一点的批评或建议将不胜感激。
对于不使用dataclasses
的示例,我想正确的方法是在子类中覆盖__new__
。 我怀疑由于dataclasses
的特殊工作方式,我尝试覆盖__new__
在这里失败了。 你会同意吗?
谢谢您的意见。
不要使用assert
。 利用
if len(self) != 1:
raise ValueError
可以使用-O
开关关闭assert
,即,如果您像这样运行脚本
python -O my_script.py
它不会再引发错误。
另一种选择是使用自定义的用户定义list
子类,它会在实例化时检查列表的len
。
from dataclasses import dataclass, field
from typing import Sequence, TypeVar, Generic
T = TypeVar('T')
class ConstrainedList(list, Generic[T]):
def __init__(self, seq: Sequence[T] = (), desired_len: int = 1):
super().__init__(seq)
if len(self) != desired_len:
raise ValueError(f'expected length {desired_len}, got {len(self)}. items={self}')
@dataclass(frozen=True)
class MyData:
id: int = field()
data: ConstrainedList[float] = field(default_factory=ConstrainedList)
@dataclass(frozen=True)
class MySpecialData(MyData):
...
# correctly throws exception
special_data = MySpecialData(id=1, data=ConstrainedList([2, 3]))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.