【发布时间】:2019-01-15 04:42:11
【问题描述】:
我有一个 Python 类,它的字段可以传递几种序列类型之一。为了简化,我将坚持使用元组和列表。 __init__ 将参数转换为MyList。
from typing import Union
from dataclasses import dataclass, InitVar, field
class MyList(list):
pass
@dataclass
class Struct:
field: Union[tuple, list, MyList]
def __post_init__(self):
self.field = MyList(self.field)
field 声明应该使用什么类型?
- 如果我提供所有可能输入类型的联合,则代码不会记录
field在访问时始终是MyList。 - 如果我只提供最后的
MyList类型,PyCharm 会在我传递Struct()和list时报错。
我可以改用:
_field: InitVar[Union[tuple, list, MyList]] = None
field: MyList = field(init=False)
def __post_init__(self, _field):
self.field = MyList(_field)
但这非常难看,尤其是在跨 3 个字段重复时。此外,我必须构造一个类似 Struct(_field=field) 的结构,而不是 Struct(field=field)。
2018年4月,“tm”在PyCharm的公告上评论了这个问题:https://blog.jetbrains.com/pycharm/2018/04/python-37-introducing-data-class/#comment-323957
【问题讨论】:
-
This discussion on github 涉及转换器的问题,在我看来,这似乎是您所要求的,以及为什么它们不是数据类的一部分。您当前使用
InitVar的实现是您的方案的预期解决方案。 -
我的转换器用例之一是将用户输入(通过 YAML 文件)转换为我的配置结构的类型安全枚举。也许我会使用包装构造函数并转换输入的函数来完成此操作。至于我将 ndarray 转换为 MyArray 的其他用例,我将不得不查看我的代码以找到我喜欢的解决方案。
-
我明白了。那么,另一种选择是切换到支持转换器的attrs。并且不相关,但是自从您提出以来,
yaml.load对用户输入是不安全的。除非您可以信任您的用户,否则您应该使用yaml.safe_load。 -
哦,是的,我使用 ruamel.yaml,我相信所有加载程序(包括往返)都是安全的,除了“不安全”。
-
不要使用数据类。