【问题标题】:Is there "on_getattr" equivalent functionality for attrs package?attrs 包是否有“on_getattr”等效功能?
【发布时间】:2021-11-22 18:48:52
【问题描述】:

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

对于 setter attrs 有一个方便的参数 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

更新

一种解决方案是使用/覆盖 attr 的 __getattribute__ 来添加如下逻辑:

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

【问题讨论】:

    标签: python python-3.x oop python-attrs


    【解决方案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
    

    您应该通过更少的魔法元编程获得所有好处。

    注意_name will still be name__init__ 参数。

    【讨论】:

    • 剥离“_”可以解决我的问题。谢谢
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-31
    • 2010-11-28
    • 2011-02-13
    • 2020-09-07
    相关资源
    最近更新 更多