attrs包是否存在与on_setattr功能对等的on_getattr相关特性?
attrs 本身提供了原生的自定义 getter 逻辑支持,不需要通过重写魔法方法或者额外定义异名属性的方式实现,下面是两种最常用的落地方案:
方案1:使用 attrs 22.2+ 内置的 getter 参数(官方推荐)
这个参数就是专门为属性读取时添加自定义逻辑设计的,不需要修改原有属性命名,所有 attrs 原生特性(包括 on_setattr、字段校验、__repr__、序列化能力等)都可以完全兼容,用法如下:
import attr # 自定义getter逻辑,固定接收三个参数:类实例、字段定义对象、存储的原始值 def name_getter(instance, field, raw_value): return raw_value.upper() @attr.s(kw_only=True) class Customer: name = attr.ib( type=str, on_setattr=[prevent_empty_string, other_validators_or_logics], # 直接指定getter函数即可 getter=name_getter )
使用时直接正常读取 customer.name 就会自动触发自定义逻辑,拿到处理后的值。
方案2:私有存储字段+同名property(兼容低版本attrs)
如果你使用的 attrs 版本低于22.2,没有内置 getter 参数,可以用这种兼容性更强的方案:将实际存储值的字段设为私有属性,对外暴露同名的 property 处理读写逻辑,原有的 on_setattr 逻辑作用在私有存储字段上不会失效。
import attr @attr.s(kw_only=True) class Customer: # 私有存储字段,设置repr=False避免__repr__打印私有属性 _name = attr.ib( type=str, on_setattr=[prevent_empty_string, other_validators_or_logics], repr=False ) @property def name(self): # 自定义getter逻辑 return self._name.upper() # 如果需要支持赋值,补充setter即可,on_setattr逻辑仍会生效 @name.setter def name(self, value): self._name = value
这种方案对外的接口和普通属性完全一致,也不会破坏 attrs 的原生特性。
不推荐方案说明
- 额外定义异名属性(比如
get_name):会导致类对外暴露两套属性接口,使用起来不直观,也不符合Python的编码习惯 - 重写
__getattribute__:会引入大量分支判断提升维护成本,同时会改变所有属性读取的默认逻辑,很容易破坏 attrs 内置的__repr__、序列化等能力,性能也会有劣化。
内容的提问来源于stack exchange,提问作者omid
相关产品推荐
相关产品推荐

