attrs 包是否有"on_getattr"等效功能?



我为我的实体使用attrs包,它在大多数情况下工作得很好。我遇到的一个问题是在定义getter时对于属性(通常在纯python中@property)是goto

对于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中是否有任何方法可以用于这种情况,或者如果没有,除了定义另一个具有不同名称的属性之外,还有什么其他解决方案,即

@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__

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

如果你这样做:

@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

你应该用更少的神奇元编程获得所有的好处。

注意:_name__init__参数仍然是name

相关内容

  • 没有找到相关文章

最新更新