如何编写重写__getattribute__/__getattr__的类装饰器且保留内部原实现?
类装饰器重写
__getattribute__问题解答 1. 能否用类装饰器重写__getattribute__或__getattr__?
完全可以。类装饰器的核心就是接收目标类作为参数,通过修改类的方法、属性或创建子类的方式扩展类行为,自然能添加或重写__getattribute__、__getattr__这类特殊方法。
2. 如何在类接口层面重写但不影响内部实现?
关键要区分类内部属性访问和外部公共接口访问:内部代码(比如__init__里的self._args = args)必须用原生属性获取逻辑,外部调用(比如obj.some_method())才触发自定义重载逻辑。
实现思路:
- 在自定义
__getattribute__中判断属性名:如果是内部属性(通常以_开头),直接调用object.__getattribute__(Python最底层的属性获取方法); - 公共属性/方法则执行自定义的重载逻辑。
修正后的待装饰类代码
原示例存在语法错误,先修正为可运行版本:
import itertools class MultitudeOfThings: def __init__(self, *args, **kwargs): if len(kwargs) > 0: raise NotImplementedError() self._args = args self._kwargs = kwargs def __copy__(self, *args, **kwargs): if len(kwargs) > 0: raise NotImplementedError() left = self._args[0] leftovers = self._args[1:] return type(self)(itertools.chain([left], leftovers))
装饰器实现代码
def decorate(cls): # 保存类原本的__getattribute__方法 original_getattribute = cls.__getattribute__ def custom_getattribute(self, attrname: str): # 内部属性(以_开头)使用原始逻辑获取 if attrname.startswith('_'): return original_getattribute(self, attrname) # 公共属性/方法执行自定义重载逻辑 return type(self)(getattr(arg, attrname) for arg in self._args) # 替换类的__getattribute__方法 cls.__getattribute__ = custom_getattribute return cls
使用示例
@decorate class MultitudeOfThings: # 类实现同上... pass # 测试内部属性不受自定义逻辑影响 obj = MultitudeOfThings(1, 2, 3) print(obj._args) # 输出: (1, 2, 3),用原始__getattribute__获取 # 测试公共接口的重载逻辑 # 给每个元素执行+5操作,生成新实例 result = obj.__add__(5) print([x for x in result._args]) # 输出: [6, 7, 8]
关键说明
- 装饰器中保存了原始
__getattribute__,确保内部访问self._args这类属性时不会触发自定义逻辑; - 用
_前缀区分内部属性,也可根据需求调整判断规则(比如指定固定的内部属性列表); - 如果用
__getattr__替代__getattribute__,逻辑会更简单:__getattr__仅在属性找不到时触发,内部属性会被原生逻辑直接找到,不会进入自定义方法,但它无法拦截已存在的属性访问,适合动态属性场景。
内容的提问来源于stack exchange,提问作者Toothpick Anemone
相关产品推荐
相关产品推荐

