1

我为我的实体使用attrs包,在大多数情况下它就像一个魅力。我面临的一个问题是为属性定义getter(通常在纯python中@property是goto)

for setterattrs有一个方便的参数on_setattr,其工作方式如下:

@attr.s(kw_only=True)
class Customer:
    name = attr.ib(type=str, on_setattr=[prevent_empty_string, other_validators_or_logics, ])

它使我们免于@name.setter在任何情况下几乎使用(至少在我的经验中)

但是,当我们在返回属性时有一些逻辑时,当然,我们不能使用:

@property
def name(...

因为它将覆盖我们 attrs 名称的原始定义。所以我想知道在attrs这种情况下是否有任何内置方法,或者如果没有其他解决方案,除了定义另一个具有不同名称的属性,即

@property
def get_name(self):
    return self.name # or whatever

更新

一个解决方案是使用/覆盖__getattribute__attr 来添加类似的逻辑:

@attr.s(kw_only=True)
class Customer:
    name = attr.ib(type=str, on_setattr=[prevent_empty_string, other_validators_or_logics, ])

    def __getattribute__(self, name: str) -> Any:
        if name == "name":
            return self.__dict__["name"].upper()
        return super().__getattribute__(name)

但最终,它会被大量 if/switch 块污染,更重要的是会与内置函数混淆__repr__

4

1 回答 1

1

没有……到目前为止,假设是对于您的用例,您将拥有一个私有属性并在其之上定义一个属性。

如果您执行以下操作:

@attr.define
class Customer:
    _name: str = attr.field(on_setattr=[…])

    @property
    def name(self) -> str:
        return self._name.upper()

    @name.setter
    def name(self, value: str) -> None:
        self._name = value

你应该用更少的魔法元编程来获得所有的好处。

NB 的__init__论点_name 仍然是name.

于 2021-10-02T12:20:54.430 回答