【问题标题】:frozen and hashable dataclass with Iterable field具有可迭代字段的冻结和可散列数据类
【发布时间】:2019-06-13 08:56:33
【问题描述】:

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

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

感谢attrs 转换器,我能够提供灵活的API,客户端可以使用list、set 或dict_keys 等各种类型实例化my_field。在创建类之前,它们都会自动转换为tuple。

我可以使用dataclasses 保留此 API 吗?

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

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


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

【问题讨论】:

  • 您的问题可能有解决方案。只有您的问题不包含MCVE,而且很难看出您的转换究竟是如何进行的。请提供一个完整的例子。
  • 嗨 sophros,我认为在我的问题的上下文中它是不言自明的,因为 attrs 提供了一个转换器参数。尽管如此,我还是添加了一个 sn-p。

标签: python converters python-dataclasses python-attrs


【解决方案1】:

在 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))

【讨论】:

    【解决方案2】:

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

    DC 严格来说是 attrs 的一个子集,它不太可能永远改变。

    【讨论】:

    • 感谢您的信息。我希望在类被冻结之前可能有一个技巧来模拟转换步骤,也许是通过一些元类。可惜没有包含转换功能。
    猜你喜欢
    • 2023-01-18
    • 1970-01-01
    • 2019-04-20
    • 2016-10-26
    • 2014-09-14
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 1970-01-01
    相关资源
    最近更新 更多