2

现在我终于放弃了对 Python 2 的支持,我正在从 Python 3 迁移attrs到 Python 3 dataclasses,并且有一个问题让我特别苦恼。

假设我有一个冻结且可散列的类MyClass,其中一个字段my_field为 type tuple

多亏了attrs转换器,我能够提供灵活的 API,客户端能够my_field使用各种类型进行实例化,例如list,setdict_keys. 在创建类之前,它们都会自动转换为 a tuple

我可以保留这个 APIdataclasses吗?

根据要求,一个小代码示例:

@attr.s(frozen=True, hash=True)
class MyClass:
    my_field = attr.ib(default=tuple(), converter=tuple)


print(MyClass([1, 2, 3]))
4

2 回答 2

3

在 post_init 步骤中通过基类设置属性值似乎可行:

@dataclass(frozen=True)
class MyClass:
    my_field: Sequence[str]

    def __post_init__(self):
        super().__setattr__('my_field', tuple(getattr(self, 'my_field')))

混合实现:

class ValidationError(AttributeError):
    pass


class ConversionValidationField(Field):

    def __init__(self, default=MISSING, default_factory=MISSING, init=True, repr=True,
                 hash=None, compare=True, metadata=None, converter=None, validator=None):
        self.converter = converter
        self.validator = validator
        super().__init__(default, default_factory, init, repr, hash, compare, metadata)


class ConversionValidationMixin:

    def __post_init__(self):
        for field in fields(self):
            if isinstance(field, ConversionValidationField):
                if field.converter:
                    super().__setattr__(field.name, field.converter(getattr(self, field.name)))

                if field.validator:
                    if not field.validator(getattr(self, field.name)):
                        raise ValidationError('Validation failed for {}.'.format(field.name))
于 2019-01-26T11:31:01.770 回答
1

不,转换器是数据类 PEP 选择不实现以保持简单的事情之一。http://www.attrs.org/en/stable/why.html#data-classes提到了更多。

DC 严格来说是其中的一个子集,attrs而且它永远不会改变。

于 2019-01-20T07:40:52.263 回答